打破冷漠僵局文章

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

无需赘述,线程可以处于多种状态之一,如下面的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锁定其fromAccount ,编号2和尝试锁定其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

打破冷漠僵局文章

打破冷漠僵局文章_研究僵局–第1部分相关推荐

  1. 打破冷漠僵局文章_研究僵局–第2部分

    打破冷漠僵局文章 调查死锁时最重要的要求之一就是要研究死锁. 在我的上一个博客中,我写了一些名为DeadlockDemo代码,该代码使用一堆线程在一系列银行账户之间转移随机数,然后陷入僵局. 该博客运 ...

  2. 打破冷漠僵局文章_研究僵局–第3部分

    打破冷漠僵局文章 在本系列的前两个博客( 第1部分和第2部分)中 ,我演示了如何创建一段会死锁的错误代码,然后使用该代码演示进行线程转储的三种方式. 在此博客中,我将分析线程转储以找出错误的原因. 下 ...

  3. 打破冷漠僵局文章_保持冷静并打破僵局-最佳

    打破冷漠僵局文章 Hack The Box (HTB) is an online platform allowing you to test your penetration testing skil ...

  4. 单脉冲雷达的相干干扰的研究文章_什么是量子纠缠和量子退相干?这个比喻太绝了!...

    God does not play dice with the universe. "无论如何,我都确信,上帝不会掷骰子." --爱因斯坦 1905年,爱因斯坦使用量子理论对光电效 ...

  5. 研究僵局–第4部分:修复代码

    在这个简短的博客系列的最后BadTransferOperation中,我一直在讨论分析死锁,我将修复BadTransferOperation代码. 如果您看过本系列的其他博客 ,那么您将知道,为了达到 ...

  6. 打破学习的玻璃墙_打破Google背后的创新深度学习

    打破学习的玻璃墙 What Google Translate does is nothing short of amazing. In order to engineer the ability to ...

  7. 图书漂流系统的设计和研究_研究在设计系统中的作用

    图书漂流系统的设计和研究 Having spent the past 8 months of my academic career working co-ops and internships in ...

  8. 波形包络提取与峰值提取_研究提出从地震噪声提取微弱体波信号探测下地幔散射体的方法...

    下地幔占地球体积近60%,在各种尺度上都表现出强烈的不均匀性.对下地幔不均匀体特别是小尺度散射体的分布.形态和性质的研究,可以为认识地球深部物质组成及相变.地幔流变性.地幔对流尺度.地幔混合效率等提供 ...

  9. 多元相关性分析_研究 | 精神分裂症症状与超氧化物歧化酶相关性的性别差异

    精神分裂症是一种精神病综合征,主要症状包括阳性症状(如幻觉.妄想以及言语混乱),阴性症状(如积极性降低.表达能力下降),认知缺陷(如执行功能.记忆能力和心理处理速度受损).氧化应激过度.抗氧化防御系统 ...

最新文章

  1. 期未课程设计:基于SSM的产品销售管理系统
  2. python适用范围_Python应用范围总结概览
  3. 数字图像处理系统组成 及研究内容
  4. 滴滴全链路压测解决之道 | 技术头条
  5. Keras中CNN联合LSTM进行分类
  6. (四) 制作一个最简单的qt界面
  7. Maven环境变量配置不成功
  8. 离散数据:析取范式与合取范式
  9. 对日软件工程师的几种招聘要求
  10. 开源一个 Python 中文数据结构和算法教程
  11. MongoDB简单学习小总结
  12. PayPal 如何付款
  13. python三国演义人物出场统计ppt_Python统计三国演义主要人物出场次数
  14. linux查看日志常用命令
  15. Android8.1 源码修改之插入SIM卡默认启用Volte功能
  16. 多语言适配之阿拉伯语
  17. ComponentOne C1ReportDesigner 设计报表
  18. 三公到底指太师太傅太保还是…
  19. 应用回归分析之岭回归(Ridge Regression,RR)
  20. 纯JSP简单登录实例

热门文章

  1. Oracle入门(十三B)之高级查询(上)
  2. Oracle入门(三A)之sqlplus
  3. Hibernate注解(二)之映射简单的属性
  4. Selector 实现原理
  5. Shell入门(一)之简介
  6. 教你一招快速打开idea的秘诀
  7. 用赫夫曼树进行文件解压
  8. idea初始化git 初始化git仓库
  9. vba mysql update多字段_vba操作Mysql使用UPDATE一次更新多组数据
  10. django mysql 创建表_关于 django ORM 中,数据库建表方式的问题