文章目录
jstack定位死锁
- jstack定位死锁
- 两个线程死锁分析
- 多个线程死锁分析
死锁发生的时候, 控制台什么也不打印, 无法进行排查. 这个时候就需要借助工具来进行定位死锁了. 工具之一就是jdk自带的命令jstack
在jdk的bin 目录中,可以看到是有jstack.exe
这个应用程序的,配置好了jdk的环境变量后,那么就可以直接用jstack来分析死锁了.
首先分析两个线程死锁的情况 运行之前的章节中, 两个线程必然发生死锁的代码demo
package com.thread.deadlock;
/**
* 类名称:MustDeadLock
* 类描述: 必定发生死锁的情况
*
* @author: https://javaweixin6.blog.csdn.net/
* 创建时间:2020/9/8 7:55
* Version 1.0
*/
public class MustDeadLock implements Runnable {
//标记位, 不同的线程根据标记位执行不同的代码
int flag = 1 ;
//两把锁
static Object o1 = new Object();
static Object o2 = new Object();
public static void main(String[] args) {
MustDeadLock r1 = new MustDeadLock();
MustDeadLock r2 = new MustDeadLock();
//给不同的线程, 设置不同的标记位
r1.flag=1;
r2.flag=2;
Thread t1 = new Thread(r1);
Thread t2 = new Thread(r2);
t1.start();
t2.start();
}
@Override
public void run() {
//打印出标记位
System.out.println("flag = "+flag);
if (flag == 1) {
synchronized (o1) {
try {
//线程1持有锁o1, 并且等待500ms ,让线程2执行
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
//线程1尝试去获取锁o2
synchronized (o2) {
System.out.println("线程1成功拿到两把锁");
}
}
}
if (flag == 2) {
synchronized (o2) {
try {
//持有锁o2, 并且等待500ms ,让线程1执行
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
//线程2尝试去获取锁o1
synchronized (o1) {
System.out.println("线程2成功拿到两把锁");
}
}
}
}
}
运行程序 , 可以看到控制台打印了1 和2之后, 再也没打印出东西了, 也没报错, 但是可以看到红色的按钮是亮着的,程序进入了阻塞的状态. 首先用jps 找出当前运行程序的PID, 可以看到我们自己运行的类MustDeadLock的PID为10052
输入
jstack 10052
可以看到打印出来了线程间死锁的信息. 线程1持有0x000000076e471818
这把锁, 需要0x000000076e471808
这把锁. 线程0持有0x000000076e471808
这把锁,需要0x000000076e471818
这把锁.因此就造成了死锁. 把打印信息拖到最下面, 也可以看到 提示发现了一个死锁
Found 1 deadlock
运行如下的多人转账的代码案例
package com.thread.deadlock;
import java.util.Random;
/**
* 类名称:MultiTransferMoney
* 类描述: 多人转账发生死锁demo
*
* @author: https://javaweixin6.blog.csdn.net/
* 创建时间:2020/9/9 7:13
* Version 1.0
*/
public class MultiTransferMoney {
//账户的总数量
private static final int NUM_ACCOUNTS = 500;
//每个账户初始的余额
private static final int NUM_MONEY = 1000;
private static final int NUM_ITERATIONS = 1000000;
private static final int NUM_THREADS = 20;
public static void main(String[] args) {
Random random = new Random();
//定义转账的账户数组
TransferMoney.Account[] accounts = new TransferMoney.Account[NUM_ACCOUNTS];
for (int i = 0; i
关注
打赏
最近更新
- 深拷贝和浅拷贝的区别(重点)
- 【Vue】走进Vue框架世界
- 【云服务器】项目部署—搭建网站—vue电商后台管理系统
- 【React介绍】 一文带你深入React
- 【React】React组件实例的三大属性之state,props,refs(你学废了吗)
- 【脚手架VueCLI】从零开始,创建一个VUE项目
- 【React】深入理解React组件生命周期----图文详解(含代码)
- 【React】DOM的Diffing算法是什么?以及DOM中key的作用----经典面试题
- 【React】1_使用React脚手架创建项目步骤--------详解(含项目结构说明)
- 【React】2_如何使用react脚手架写一个简单的页面?