研究僵局–第1部分

我敢肯定我们都去过那里:太晚了,您饿了,服务器已挂起,或者应用程序正在以蜗牛的速度运行,并且有人喘着气想要您解决问题,然后再去解决。 您的应用程序意外挂起的可能原因之一是称为死锁的线程问题。

无需赘述,线程可以处于多种状态之一,如下面的UML状态图所示……

…死锁与BLOCKED状态有关,API文档将其定义为“一个等待监视器锁定而被阻塞的线程”。

那么,什么是僵局? 简而言之,在给定两个线程A和B的情况下,当线程A由于等待线程B释放监视器锁定而阻塞时,而线程B因等待线程A释放相同的监视器锁定而阻塞而发生死锁。

但是,事情可能比这更复杂,因为死锁可以包含一堆线程。 例如,线程A因为正在等待线程B而阻塞,线程B因为正在等待线程C而阻塞,线程C因为正在等待线程D而阻塞,所以线程D因为正在等待E,E而阻塞,因为它正在等待F和F阻塞,因为它正在等待A。

诀窍是找出哪些线程被阻塞以及为什么被阻塞,这是通过从应用程序中获取线程转储来完成的。 线程转储只是快照报告,显示给定时间点所有应用程序线程的状态。 有几种工具和技术可以帮助您掌握线程转储,其中包括jVisualVMjstack和unix kill命令。 但是,在获取和解释线程转储之前,我需要一些代码来创建死锁

我为此选择的方案是简单的银行帐户转帐之一。 这个想法是,有一个余额转移程序正在运行,该程序使用一堆线程在不同帐户之间随机转移各种金额。 在此程序中,使用以下非常简单的Account类来表示银行帐户:

public class Account {private final int number;private int balance;public Account(int number, int openingBalance) {this.number = number;this.balance = openingBalance;}public void withdraw(int amount) throws OverdrawnException {if (amount > balance) {throw new OverdrawnException();}balance -= amount;}public void deposit(int amount) {balance += amount;}public int getNumber() {return number;}public int getBalance() {return balance;}
}

上面的类对具有帐户号和余额属性以及诸如deposit(...)withdraw(...)类的操作的银行帐户进行建模。 如果要提取的金额大于可用余额,则withdraw(...)将引发一个简单的检查异常OverdrawnException

示例代码中其余的类是DeadlockDemo及其嵌套类BadTransferOperation

public class DeadlockDemo {private static final int NUM_ACCOUNTS = 10;private static final int NUM_THREADS = 20;private static final int NUM_ITERATIONS = 100000;private static final int MAX_COLUMNS = 60;static final Random rnd = new Random();List<Account> accounts = new ArrayList<Account>();public static void main(String args[]) {DeadlockDemo demo = new DeadlockDemo();demo.setUp();demo.run();}void setUp() {for (int i = 0; i < NUM_ACCOUNTS; i++) {Account account = new Account(i, rnd.nextInt(1000));accounts.add(account);}}void run() {for (int i = 0; i < NUM_THREADS; i++) {new BadTransferOperation(i).start();}}class BadTransferOperation extends Thread {int threadNum;BadTransferOperation(int threadNum) {this.threadNum = threadNum;}@Overridepublic void run() {for (int i = 0; i < NUM_ITERATIONS; i++) {Account toAccount = accounts.get(rnd.nextInt(NUM_ACCOUNTS));Account fromAccount = accounts.get(rnd.nextInt(NUM_ACCOUNTS));int amount = rnd.nextInt(1000);if (!toAccount.equals(fromAccount)) {try {transfer(fromAccount, toAccount, amount);System.out.print(".");} catch (OverdrawnException e) {System.out.print("-");}printNewLine(i);}}// This will never get to here...System.out.println("Thread Complete: " + threadNum);}private void printNewLine(int columnNumber) {if (columnNumber % MAX_COLUMNS == 0) {System.out.print("\n");}}/*** The clue to spotting deadlocks is in the nested locking - synchronized keywords. Note that the locks DON'T* have to be next to each other to be nested.*/private void transfer(Account fromAccount, Account toAccount, int transferAmount) throws OverdrawnException {synchronized (fromAccount) {synchronized (toAccount) {fromAccount.withdraw(transferAmount);toAccount.deposit(transferAmount);}}}}
}

DeadlockDemo提供了创建DeadlockDemo的应用程序框架。 它有两个简单的任务: setup()run()setup()创建10个帐户,并使用一个帐号和一个随机的期初余额对其进行初始化。 run()创建嵌套类BadTransferOperation 20个实例,该实例仅扩展Thread并使它们开始运行。 请注意,用于线程数和帐户数的值完全是任意的。

BadTransferOperation是所有动作发生的地方。 它的run()方法循环执行10000次,从accounts列表中随机选择两个帐户,并将0到1000之间的随机数从一个accounts转移到另一个accounts 。 如果fromAccount中的资金不足,则会引发异常,并在屏幕上显示“-”。 如果一切顺利,并且传输成功,则为“。”。 在屏幕上打印。

问题的核心是包含FAULTY同步代码的方法transfer(Account fromAccount, Account toAccount, int transferAmount)

synchronized (fromAccount) {synchronized (toAccount) {fromAccount.withdraw(transferAmount);toAccount.deposit(transferAmount);}}

此代码首先锁定fromAccount ,然后toAccount转移现金,随后释放这两个锁定前。

给定两个线程A和B以及帐户1和2,则线程A锁定其编号为1的fromAccount并尝试将其锁定为帐户2的toAccount ,将出现问题。同时,线程B锁定其编号2和2的fromAccount 。尝试锁定其toAccount ,即帐户号1。因此,线程A在线程B上被toAccount ,线程B在线程A上被阻塞–死锁。

如果运行此应用程序,则将获得一些类似于以下内容的输出:

…随着程序突然停止。

现在,我有一个死锁的应用程序,我的下一个博客实际上将掌握线程转储,并了解它的全部含义。

参考: Captain Debug's Blog博客中的调查死锁-第1部分,来自我们的JCG合作伙伴 Roger Hughes。


翻译自: https://www.javacodegeeks.com/2012/10/investigating-deadlocks-part-1.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/370901.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

使用Vue.js和Axios从第三方API获取数据 — SitePoint

更多的往往不是&#xff0c;建立你的JavaScript应用程序时&#xff0c;你会想把数据从远程源或消耗一个[ API ]&#xff08;https&#xff1a;/ /恩。维基百科。org /维基/ application_programming_interface&#xff09;。我最近看了一些[公开]&#xff08;https://github.co…

区位码怎么知道点阵里的起始点_自身免疫疾病的GAPS起始饮食改良版

写这篇文章的原因如果您已经关注我的博客一段时间&#xff0c;您知道我开始使用GAPS饮食&#xff0c;然后转换到AIP饮食&#xff0c;因为我仍在努力治疗炎症和自身免疫的发作。 Katy Haldiman 有同样的经历&#xff0c;我们并不孤单。许多患有自身免疫性疾病的人在 GAPS 上挣扎…

微信小程序APP(商超营销类)经验总结

项目介绍 这是一款主打门店营销的小程序。包括首页、门店、营销、个人设置、登录、数据统计展示、营销设置等。 本来要独立完成整个项目&#xff0c;包括前后端一套的&#xff0c;有些意外因素&#xff0c;项目临时收尾&#xff08;说明&#xff1a;只完成了前端的部分&#…

excel不显示0_Excel数字过长不能完整显示?超长数字变为0

Excel中计算规则和限制设定数值精确度为15位&#xff01;超过15位后&#xff0c;数字会显示为0excel数字超过15位&#xff0c;会显示为0&#xff0c;超过10位&#xff0c;默认采用科学计数法显示1、如何解决超长数字输入&#xff0c;全部显示问题&#xff1f;&#xff08;单元格…

Android天气预报设计

——嵌入式软件开发 名字功能模块代码行数备注谢灿辉Widget200桌面小程序李杨敏GPS定位&#xff0c;百度地图API100-150获取当前所在城市丁小芳城市选择Activity&#xff0c;天气API获取天气100-200包括数据库交互本软件是一个天气类应用软件&#xff0c;带有widget&#xff0c…

算法笔记_164:算法提高 最小方差生成树(Java)

目录 1 问题描述 2 解决方案 1 问题描述 问题描述给定带权无向图&#xff0c;求出一颗方差最小的生成树。输入格式输入多组测试数据。第一行为N,M&#xff0c;依次是点数和边数。接下来M行&#xff0c;每行三个整数U,V,W&#xff0c;代表连接U,V的边&#xff0c;和权值W。保证图…

layui数据表格(一:基础篇,数据展示、分页组件、表格内嵌表单和图片)

表格展示神器之一&#xff1a;layui表格 前言&#xff1a;在写后台管理系统中使用最多的就是表格数据展示了&#xff0c;使用表格组件能提高大量的开发效率&#xff0c;目前主流的数据表格组件有bootstrap table、layui table、easyUI table等.... 博主个人比较倾向于layui&am…

算法设计与分析_算法设计与分析(第2版)第2章分治策略回顾

YI时间&#xff5c;外刊&#xff5c;MM-DFW&#xff5c;机器学习系列点击上方蓝字&#xff0c;关注给你写干货的松子茶分治策略是通用算法设计技术之一&#xff0c;很多有效的算法是它的特殊实现,顾名思义就是分而治之。一个问题能够用分治法求解的要素是问题能够按照某种方式分…

2017-2018-1 Java演绎法 第三周 作业

团队任务&#xff1a;团队展示与选题团队展示 队员学号及姓名 学号  姓名  主要负责工作  20162315  马军  日常统计&#xff0c;项目部分代码  20162316  刘诚昊  项目部分代码&#xff0c;代码质量测试  20162317  袁逸灏  组长 项目 主要 代码  201…

linux开机启动roscore,树莓派ubuntuMate系统中开机自启动ROS的launch文件

0x00 为何需要开机自启动launch文件在ROS开发后期阶段由于功能已经趋于稳定&#xff0c;因此就需要系统在一上电启动后就自动把ROS下的各节点程序加载运行&#xff0c;这样就省去了我们还得手动输入roslaunch命令来加载bringup的launch文件的操作。经过我的实际测试目前有两种方…

Oracle ADF移动世界! 你好!

您好&#xff0c;ADF Mobile&#xff0c;世界&#xff01; 您可能已经知道... ADF Mobile在这里&#xff01; 以下是一些链接&#xff0c;这些链接会让您有宾至如归的感觉。 ADF Mobile主页&#xff1a; http://www.oracle.com/technetwork/developer-tools/adf/overview/ad…

css 小知识点:inline/inline-block/line-height

inline: 此元素会被显示为内联元素&#xff0c;元素前后没有换行符。因此&#xff1a;无法设置宽度和高度&#xff5e; inline-block: 行内块元素。元素前后没有换行符&#xff08;CSS2.1 新增的值&#xff09; 用通俗的话讲&#xff0c;就是不独占一行的块级元素。然后拥有…

协同过滤算法_机器学习 | 简介推荐场景中的协同过滤算法,以及SVD的使用

本文始发于个人公众号&#xff1a;TechFlow&#xff0c;原创不易&#xff0c;求个关注今天是机器学习专题的第29篇文章&#xff0c;我们来聊聊SVD在上古时期的推荐场景当中的应用。推荐的背后逻辑有没有思考过一个问题&#xff0c;当我们在淘宝或者是某东这类电商网站购物的时候…

JavaOne 2012:观察与印象

当我坐在旧金山国际机场等待登上飞机返回家中时&#xff0c;我一次又一次令人满意但累人的JavaOne&#xff08;2012&#xff09;体验&#xff0c;我正在开始写这篇特别的博客文章。 自上周日的主题演讲以来&#xff0c;在会议上疯狂地撰写了约30篇博客文章之后&#xff0c;很难…

用imspost制作catia后处理_新产品开发需要做原型验证,怎么样成型制作才省钱?...

有一天一个朋友拿着一个公仔机器人的项目过来找我&#xff0c;说做200套外壳&#xff0c;问我如何省成本用最少的钱做好产品。类似一下图片的机器人一样。组装起来高200mm左右&#xff0c;内外配件总共是62个。我当时看到产品小估算重量也很轻&#xff0c;就跟他说用3D打印有快…

如何把大段文字转为带html标签的文字

开发网页的时候&#xff0c;有时候会遇到大段的隐私声明&#xff0c;用户协议等等&#xff0c;我们呀要复制粘贴展示出来&#xff0c;必须加大量的p标签&#xff0c;h1,h2&#xff0c;空格符&#xff0c;br标签&#xff0c;这对我们来说无疑是泪崩的&#xff0c;有个很好的办法…

使用MongoDB进行事件流

MongoDB是一个非常出色的“ NoSQL”数据库&#xff0c;具有广泛的应用程序。 在SoftwareMill开发的一个项目中&#xff0c;我们将其用作复制的事件存储&#xff0c;然后将事件从事件流传输到其他组件。 介绍 基本思想非常简单&#xff08;另请参阅Martin Fowler关于Event Sou…

c语言实训作业总结,c语言程序设计上机实践心得报告

c语言程序设计上机实践心得报告 班级:11 电信 2 姓名:莫金波 学号:1107032242012.12.28 惠州学院 HUIZHOU UNIVERSITY 我们专业的学生在专业老师的带领下进行了 c 语言设计基础教程的 实践学习。在这之前&#xff0c;我们已经对 c 语言这门课程学习了差不多一 个学期&#xff0…

JavaOne 2012:在JVM上诊断应用程序

值得参加Staffan Larsen &#xff08;Oracle Java Serviceability Architect&#xff09;的演讲“ 在JVM上诊断应用程序 ”&#xff08;Hilton Plaza A / B&#xff09;&#xff0c;只是为了学习Oracle JVM 7随附的新jcmd命令行工具。该演示对我来说是“奖金”&#xff0c;这对…

文档词频矩阵_论文理解:从词嵌入到文档距离

论文作者简介本论文第一作者Matt J. Kusner是牛津大学的副教授&#xff0c;致力于设计适应现实世界问题需求的新机器学习模型&#xff08;例如&#xff0c;fair algorithms, discrete generative models, document distances, privacy, dataset compression, budgeted learning…