死锁代码
java
public void threadLock() {
Thread thread1 = new Thread(() -> {
synchronized (resource1) {
System.out.println(Thread.currentThread().getName() + " got resource1 lock.");
try {
Thread.sleep(100); // 模拟工作时间,让死锁更容易观察到
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + " trying to get resource2 lock.");
synchronized (resource2) { // 尝试获取resource2的锁
System.out.println(Thread.currentThread().getName() + " got resource2 lock.");
}
}
}, "Thread 1");
Thread thread2 = new Thread(() -> {
synchronized (resource2) {
System.out.println(Thread.currentThread().getName() + " got resource2 lock.");
try {
Thread.sleep(100); // 模拟工作时间
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + " trying to get resource1 lock.");
synchronized (resource1) { // 尝试获取resource1的锁
System.out.println(Thread.currentThread().getName() + " got resource1 lock.");
}
}
}, "Thread 2");
thread1.start();
thread2.start();
}
1. 使用 jstack
命令
jstack
属于 JDK 自带的工具,能够打印出 Java 进程中线程的堆栈信息,从而协助发现死锁。
-
步骤:
- 先通过
jps
命令获取 Java 进程的 ID。 - 再使用
jstack <pid>
命令打印线程的堆栈信息。 - 查看输出结果,若存在死锁,
jstack
会给出相关提示。
- 先通过
-
示例:
bash
yaml
# 获取Java进程ID
jps
# 假设进程ID为1234,打印线程堆栈信息
jstack 1234
2. 使用 VisualVM 工具
VisualVM 是一个可视化的监控工具,它能查看 Java 应用程序的性能和线程信息,也能检测死锁。
-
步骤:
- 打开 VisualVM 工具。
- 选择要监控的 Java 进程。
- 切换到 "线程" 标签页,点击 "线程 Dump" 按钮。
- 若存在死锁,VisualVM 会以图形化方式展示。
3. 使用 Java Mission Control(JMC)
Java Mission Control 是一个功能强大的工具,可用于监控和分析 Java 应用程序。它能实时监控线程状态,检测死锁。
-
步骤:
- 打开 Java Mission Control 工具。
- 连接到要监控的 Java 进程。
- 在 "线程" 视图中查看线程状态,若存在死锁,JMC 会给出相应提示。
4. 使用 jdk自带的jconsole.exe
-
步骤:
- 进入到bin目录。
- 运行jconsole.exe。
- 连接到要监控的 Java 进程
5. 使用Arthas排查问题
-
启动 Arthas: java -jar arthas-boot.jar
-
查看总体使用情况: dashboard
可以看到已经有死锁线程了
- 查看总体线程使用情况: thread
BLOCKED线程数量:2,并且显示了具体的BLOCKED线程
- 定位死锁的位置: thread -b
查看死锁线程详细信息:
thread 49
thread 48