打破冷漠僵局文章_研究僵局–第1部分
打破冷漠僵局文章
无需赘述,线程可以处于多种状态之一,如下面的UML状态图所示……
…死锁与BLOCKED状态有关,API文档将其定义为“一个等待监视器锁定而被阻塞的线程”。
那么,什么是僵局? 简而言之,在给定两个线程A和B的情况下,当线程A由于等待线程B释放监视器锁定而阻塞时,线程B因等待线程A释放相同的监视器锁定而阻塞而发生死锁。
但是,事情可能比这更复杂,因为死锁可能包含一堆线程。 例如,线程A因为正在等待线程B而阻塞,线程B因为正在等待线程C而阻塞,线程C因为正在等待线程D而阻塞,所以线程D因为正在等待E,E而阻塞,因为它正在等待F和F阻塞,因为它正在等待A。
诀窍是找出哪些线程被阻塞以及为什么被阻塞,这是通过从应用程序中获取线程转储来完成的。 线程转储只是快照报告,显示给定时间点所有应用程序线程的状态。 有几种工具和技术可以帮助您掌握线程转储,包括jVisualVM , jstack和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部分相关推荐
- 打破冷漠僵局文章_研究僵局–第2部分
打破冷漠僵局文章 调查死锁时最重要的要求之一就是要研究死锁. 在我的上一个博客中,我写了一些名为DeadlockDemo代码,该代码使用一堆线程在一系列银行账户之间转移随机数,然后陷入僵局. 该博客运 ...
- 打破冷漠僵局文章_研究僵局–第3部分
打破冷漠僵局文章 在本系列的前两个博客( 第1部分和第2部分)中 ,我演示了如何创建一段会死锁的错误代码,然后使用该代码演示进行线程转储的三种方式. 在此博客中,我将分析线程转储以找出错误的原因. 下 ...
- 打破冷漠僵局文章_保持冷静并打破僵局-最佳
打破冷漠僵局文章 Hack The Box (HTB) is an online platform allowing you to test your penetration testing skil ...
- 单脉冲雷达的相干干扰的研究文章_什么是量子纠缠和量子退相干?这个比喻太绝了!...
God does not play dice with the universe. "无论如何,我都确信,上帝不会掷骰子." --爱因斯坦 1905年,爱因斯坦使用量子理论对光电效 ...
- 研究僵局–第4部分:修复代码
在这个简短的博客系列的最后BadTransferOperation中,我一直在讨论分析死锁,我将修复BadTransferOperation代码. 如果您看过本系列的其他博客 ,那么您将知道,为了达到 ...
- 打破学习的玻璃墙_打破Google背后的创新深度学习
打破学习的玻璃墙 What Google Translate does is nothing short of amazing. In order to engineer the ability to ...
- 图书漂流系统的设计和研究_研究在设计系统中的作用
图书漂流系统的设计和研究 Having spent the past 8 months of my academic career working co-ops and internships in ...
- 波形包络提取与峰值提取_研究提出从地震噪声提取微弱体波信号探测下地幔散射体的方法...
下地幔占地球体积近60%,在各种尺度上都表现出强烈的不均匀性.对下地幔不均匀体特别是小尺度散射体的分布.形态和性质的研究,可以为认识地球深部物质组成及相变.地幔流变性.地幔对流尺度.地幔混合效率等提供 ...
- 多元相关性分析_研究 | 精神分裂症症状与超氧化物歧化酶相关性的性别差异
精神分裂症是一种精神病综合征,主要症状包括阳性症状(如幻觉.妄想以及言语混乱),阴性症状(如积极性降低.表达能力下降),认知缺陷(如执行功能.记忆能力和心理处理速度受损).氧化应激过度.抗氧化防御系统 ...
最新文章
- 期未课程设计:基于SSM的产品销售管理系统
- python适用范围_Python应用范围总结概览
- 数字图像处理系统组成 及研究内容
- 滴滴全链路压测解决之道 | 技术头条
- Keras中CNN联合LSTM进行分类
- (四) 制作一个最简单的qt界面
- Maven环境变量配置不成功
- 离散数据:析取范式与合取范式
- 对日软件工程师的几种招聘要求
- 开源一个 Python 中文数据结构和算法教程
- MongoDB简单学习小总结
- PayPal 如何付款
- python三国演义人物出场统计ppt_Python统计三国演义主要人物出场次数
- linux查看日志常用命令
- Android8.1 源码修改之插入SIM卡默认启用Volte功能
- 多语言适配之阿拉伯语
- ComponentOne C1ReportDesigner 设计报表
- 三公到底指太师太傅太保还是…
- 应用回归分析之岭回归(Ridge Regression,RR)
- 纯JSP简单登录实例