打破冷漠僵局文章_研究僵局–第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锁定其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

打破冷漠僵局文章

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

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

相关文章

vs2008下设置.h, .lib和 .dll 的路径配置全图及其意义

文件夹: 类型文件 include: .h &#xff08;头文件&#xff09; lib: .lib &#xff08;库&#xff09; 前面二者在vs2008中通过属性来配置。 bin: .dll &#xff08;动态链接库&#xff09; 动态链接库是通过系统路径来配置的。 添加库&#xff08;libs&#xff09;文件目录 …

按键精灵调用迅雷下载文件

Set ThunderAgent CreateObject("ThunderAgent.Agent") 建立迅雷接口对象ThunderAgent.AddTask "http://10.10.10.10/电影世界/12新电影/随风而逝.rmvb", "随风而逝.rmvb", "", "", "", - 1 , 0, - 1 Ca…

POJ1821 Fence

传送门 这道题是一道很好的单调队列优化DP的例子。 题目大意是有n个工人&#xff0c;每个人可以粉刷一段长度不超过l[i]的墙&#xff0c;如果一个人粉刷了那么他必须要粉刷第s[i]块墙&#xff0c;一个人粉刷一块墙能得到p[i]的钱&#xff0c;求所有工人得到的钱的最大值。 我们…

使用Spring Security和jdbc的Spring Boot

Spring安全性是一个很棒的框架&#xff0c;可节省开发人员的大量时间和精力。 此外&#xff0c;它还具有足够的灵活性&#xff0c;可以自定义并满足您的需求。 使用JDBC和Spring Security非常容易&#xff0c;并且许多操作是自动化的。 这将是一个最小的展示。 gradle文件包含…

map 循环_被问到Spring循环依赖怎么解决?秀给面试官看!内附图解

不知道最近有没有被一道Java面试题刷爆朋友圈&#xff0c;Spring框架的循环依赖如何解决。我收到了不少粉丝的提问&#xff0c;在了解到之后&#xff0c;也去网上查询了一些资料&#xff0c;自己也询问了身边的同事&#xff0c;总结出以下几个方面&#xff0c;今天就和我来看一…

调用ThunderAgent 迅雷局域网版的开发

P2P方式的下载&#xff0c;为我们获取互联网资料提供了一个强有力的工具&#xff0c;它可以争取最大的带宽&#xff0c;获取最大的下载速度。最早采用P2P方式下载的工具有BT、电骡等&#xff0c;后来许多传统“多线程断点续传类”软件&#xff0c;也增加了对的支持&#xff0c;…

详解虚拟机中为Linux添加硬盘

Linux添加硬盘是在原来安装的硬盘空间不够或者需要使用其他硬盘上的东西时候的解决办法&#xff0c;因为大多数初学者习惯使用虚拟机&#xff0c;这里以在Vmware虚拟机中实现Linux添加硬盘的具体步骤来详细介绍说这个问题。 Vmware中为linux增加硬盘 1. 在vmware的setting中为虚…

vue 常用功能和命令

1. vue-cli 构建项目 # 全局安装 vue-cli $ npm install --global vue-clif # 创建一个基于 webpack 模板的新项目 $ vue init webpack your-project-name # 安装依赖 $ npm install # 进入项目 $ cd your-project-name # 开发版本打包并运行 $ npm run dev# 线上环境整个项目打…

项目管理最佳实践方法_项目管理:控制项目进度最佳实践

5分钟站立会议5 MinutesStand-up Meeting&#xff08;5分钟站立会议&#xff09;是实践中项目进度管理的好办法。5分钟站立会议时&#xff0c;项目团队成员在固定时间&#xff08;如每天上午8:30&#xff5e;8:35&#xff09;、固定地点&#xff0c;每天站着围在一起&#xff0…

《海龟交易法则》经典梳理

序言&#xff0c;第一&#xff5e;第三章 海归交易法则序言本书是历史上最好的5本交易学著作之一的理由&#xff1a;1&#xff0c;重要的不是交易系统而是交易者贯彻交易系统的能力。2&#xff0c;用浅显易懂的语言阐述行为金融学的某些原理如何用于交易和影响交易。3&#xff…

Unix下C程序内存泄漏检测工具Valgrind安装与使用

Valgrind是一款用于内存调试、内存泄漏检测以及性能分析的软件开发工具。 Valgrind的最初作者是Julian Seward&#xff0c;他于2006年由于在开发Valgrind上的工作获得了第二届Google-OReilly开源代码奖。 Valgrind遵守GNU通用公共许可证条款&#xff0c;是一款自由软件。 官网…

hibernate保存失败_Hibernate:保存与保存并保存或更新

hibernate保存失败save和saveOrUpdate之间的区别是什么或save和persist之间的区别是任何Hibernate面试中常见的面试问题&#xff0c;就像Hibernate中get和load方法之间的区别一样。 Hibernate Session类提供了几种通过save &#xff0c; saveOrUpdate和persist等方法将对象保存…

BZOJ 2957 楼房重建-线段树

这个题最主要的是解决一个统计答案的问题。 首先我们注意到&#xff0c;只要考虑右区间的答案统计就好了。 记左区间的最大值为K&#xff0c;当前右区间为P。 我们把当前右区间又分成两个子区间&#xff0c;s1,s2。 那么如果s1的最大值比K小&#xff0c;那么显然只要递归处理s2…

matlab 移动平均_两所高校被禁用MATLAB背后,是工业设计能力之争

不管是MATLAB&#xff0c;还是EDA&#xff0c;都指向了中国核心工业软件缺失的问题。 作者&#xff5c; Decode 邮箱&#xff5c;oudibjoutlook.com来源丨人民数字与品玩联合出品一款工科软件&#xff0c;最近成为科研界议论的焦点。2020 年 6 月 6 日开始&#xff0c;哈尔滨工…

MySQL 当记录不存在时insert,当记录存在时update

MySQL 当记录不存在时insert&#xff0c;当记录存在时更新 网上基本有三种解决方法。 第一种&#xff1a; 示例一&#xff1a;insert多条记录 假设有一个主键为 client_id 的 clients 表&#xff0c;可以使用下面的语句&#xff1a; INSERT INTO clients (client_id, client_na…

如何使用Valgrind memcheck工具进行C/C++的内存泄漏检测

英文原文&#xff1a;How to Detect Memory Leaks Using Valgrind memcheck Tool for C / C 系统编程中一个重要的方面就是有效地处理与内存相关的问题。你的工作越接近系统&#xff0c;你就需要面对越多的内存问题。有时这些问题非常琐碎&#xff0c;而更多时候它会演变成一个…

如何在Activiti中使用瞬态变量

我们昨天发布的Activiti v6 Beta3中已经加入了一个非常需要的功能-临时变量。 在本文中&#xff0c;我将向您展示一个示例&#xff0c;该示例说明如何使用瞬态变量来覆盖一些以前不可能&#xff08;或最佳&#xff09;的高级用例。 到目前为止&#xff0c;Activiti中的所有变量…

python羊车门问题_「羊车门」经典概率题中不换门选中车的概率是多少?

今天用Python求解「羊车门」经典的概率问题,对概率学基础和Python语法的灵活运用有所收货.本次「羊车门」求解过程采用的是:穷举法计算概率已验证概率学基础理论.期间重点借鉴了奥卡姆剃刀的博客和 南葱&#xff1a;「羊车门」经典概率题中不换门选中车的概率是多少&#xff1f…

非标协议外设LCD1602

概述 LCD1602 &#xff08; Liquid Crystal Display &#xff09;是一种工业字符型液晶&#xff0c;能够同时显示 1602 即 32 字符 (16 列两行) 引脚说明 第 1 脚 : VSS 为电源地 第 2 脚 : VDD 接 5V 正电源 第 3 脚 : VL 为液晶显示器对比度调整端 , 接正电源…

50: Luogu P4568 分层图

分层图最短路模板 #include <iostream> #include <cstdio> #include <cstdlib> #include <ctime> #include <queue> #include <cstring>using namespace std;const int M 2e6 5e5 10;#define gc getchar() inline int read() {int x 0…