一、简介
在使用多线程的时候最头疼的问题就是死锁了,不好排查。通过该篇文章,你可以了解常见的死锁案例,引起原因,检测死锁的常用方法以及避免死锁的写法的注意事项。
注:本文主要参考博主 wolfcode_cn 的文章 理解Java死锁之死锁检测 以及个人完善。 尊重原创。
二、死锁
2.1 常见引起原因
- 常见于使用锁嵌套
- TODO
2.2 死锁案例
package com.ucpaas.didi.util;
/**
* @author qjwyss
* @date 2019/4/1
* @description
*/
public class DeadThread {
public static void main(String[] args) {
final String A = "A";
final String B = "B";
Thread thread1 = new Thread(() -> {
System.out.println("进入" + Thread.currentThread().getName());
synchronized (A) {
try {
Thread.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (B) {
for (int i = 0; i < 6; i++) {
System.out.println(Thread.currentThread().getName() + "输出的值:" + i);
}
}
}
System.out.println(Thread.currentThread().getName() + "执行完毕");
});
Thread thread2 = new Thread(() -> {
System.out.println("进入" + Thread.currentThread().getName());
synchronized (B) {
synchronized (A) {
for (int i = 0; i < 6; i++) {
System.out.println(Thread.currentThread().getName() + "输出的值:" + i);
}
}
}
System.out.println(Thread.currentThread().getName() + "执行完毕");
});
thread1.start();
thread2.start();
}
}
正常输出结果:
进入Thread-1
进入Thread-0
Thread-1输出的值:0
Thread-1输出的值:1
Thread-1输出的值:2
Thread-1输出的值:3
Thread-1输出的值:4
Thread-1输出的值:5
Thread-1执行完毕
Thread-0输出的值:0
Thread-0输出的值:1
Thread-0输出的值:2
Thread-0输出的值:3
Thread-0输出的值:4
Thread-0输出的值:5
Thread-0执行完毕
死锁时输出结果:
进入Thread-0
进入Thread-1
三、检测方法
3.1 使用JConsole检测死锁
- 使用jdk自带的jconsole控制台查看死锁。双击jconsole.exe命令行打开控制界面,如下
- 选中当前的测试类DeadThread的进程,进行不安全链接,如下:
- 切换到线程选项卡,点击检测死锁按钮,如下:
- 此时会生成死锁页签,可以根据该页签展示的死锁线程列表去定位问题。如下:
如上,即可定位死锁位置, 建议使用多线程的时候自定义线程名称,这样比自动生成的Thread-num好识别的多。
- 原因分析TODO
3.2 使用JStack检测死锁
- 使用jdk自带的jstack命令行生成dump文件,进行分析。
- 打开cmd命令行,查询jps进程ID。
- 找到要调试的JVM进程号 pid ,这里是16872, 执行 jsatck -l pid > 文件位置 命令生成dump文件
- 使用editplus等文本工具打开生成的txt文档,查询相关死锁内容,如下:
如上,即可定位死锁位置, 建议使用多线程的时候自定义线程名称,这样比自动生成的Thread-num好识别的多。
3.3 使用ThreadMXBean检测 TODO
四、避免方法 TODO
五、多线程系列链接
- 多线程系列(一)------ 线程的状态及转换
- 多线程系列(二)------ 线程的创建方式
- 多线程系列(三)------ 线程常用方法
- 多线程系列(四)------ 线程优先级和守护线程和终止线程的方式
-
多线程系列(六)------ 生产者消费者案例
- 多线程系列(七)------ synchronized关键字简单使用以及可重入性
- 多线程系列(八)------ synchronized关键字原理以及锁优化
- volatile相关
- ThreadLocal相关
- 锁LOCK相关系列
- 原子类相关系列
- 并发集合相关系列
- 线程池相关系列