死锁模拟
在分析介绍之前,先以一个基本的死锁程序为例,我在这里只用了两个嵌套的 synchronized 去获取锁,具体如下:
package com.javapractice.concurrent;
public class DeadLockDemo extends Thread {
private String lock1;
private String lock2;
public DeadLockDemo(String lock1, String lock2) {
this.lock1 = lock1;
this.lock2 = lock2;
}
@Override
public void run() {
synchronized (lock1) {
System.out.println(Thread.currentThread().getName() + "获得资源: " + lock1);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (lock2) {
System.out.println(Thread.currentThread().getName() + "获得资源: " + lock2);
}
}
}
public static void main(String[] args) {
String lock1 = "lock1";
String lock2 = "lock2";
new DeadLockDemo(lock1, lock2).start();
new DeadLockDemo(lock2, lock1).start();
}
}
运行结果如下,可以发现出现了死锁,Thread-1在等待lock1,而Thread-0在等待lock2:
Thread-1获得资源: lock2
Thread-0获得资源: lock1
定位死锁
下面来模拟问题定位,我使用的是最常见的 jstack。
首先,可以使用 jps 或者系统的 ps 命令、任务管理器等工具,确定进程 ID。在终端中输入jsp后,发现DeadLockDemo程序的pid是83208
jps
83208 DeadLockDemo
然后,调用 jstack 获取线程栈:
jstack your_pid
此处场景在终端输入:
jstack 83208

最后,结合代码分析线程栈信息。上面这个输出非常明显,Thread-1正在等待锁<0x000000076ac26f50>,已经持有锁<0x000000076ac26f88>;而Thread-0正在等待锁<0x000000076ac26f88>,已经持有锁<0x000000076ac26f50>。 jstack 本身也会把类似的简单死锁信息抽取出来,直接打印出来。
本文通过一个简单的Java死锁程序实例,展示了如何利用jstack工具进行死锁定位。通过jps找到进程ID,然后使用jstack查看线程栈信息,分析出线程间的锁持有与等待状态,从而定位到死锁问题。
644

被折叠的 条评论
为什么被折叠?



