描述
维基百科恰当地给出了“死锁”的定义:当两个以上的运算单元,双方都在等待对方停止执行,以获取系统资源,但是没有一方提前退出时,就称为死锁。JVM 中发生死锁之后,恢复的唯一方法是重新启动 JVM。
示例
下方是一个模拟两个线程之间死锁情况的示例代码:
package com.tier1app;
public class DeadLockSimulator {
public static Object Lock1 = new Object();
public static Object Lock2 = new Object();
private static class FirstThread extends Thread {
public void run() {
synchronized (Lock1) {
System.out.println("Thread 1: Holding lock 1...");
try { Thread.sleep(10); } catch (Exception e) {}
System.out.println("Thread 1: Waiting for lock 2...");
synchronized (Lock2) {
System.out.println("Thread 1: Holding lock 1 & 2...");
}
}
}
}
private static class SecondThread extends Thread {
public void run() {
synchronized (Lock2) {
System.out.println("Thread 2: Holding lock 2...");
try { Thread.sleep(10); } catch (Exception e) {}
System.out.println("Thread 2: Waiting for lock 1...");
synchronized (Lock1) {
System.out.println("Thread 2: Holding lock 1 & 2...");
}
}
}
}
public static void main(String args[]) {
new FirstThread().start();
new SecondThread().start();
}
}
从上方的代码中,我们可以看到‘FirstThread’的执行路径:
1. 获取 Lock1 对象的锁定
2. 休眠 10 秒
3. 获取 Lock2 对象的锁定
以下是‘SecondThread’的执行路径:
1. 获取 Lock2 对象的锁定
2. 休眠 10 秒
3. 获取 Lock1 对象的锁定
如果您仔细阅读了上面的执行路径,FirstThread 在执行步骤 1 后将进入步骤 2。在步骤 2 时,SecondThread 则会执行其步骤 1。所以在 FirstThread 被唤醒并执行器步骤 3(即:尝试获取 Lock2)时,SecondThread 已经获取了 Lock2 的锁定。同样,SecondThread 执行其步骤 3(即:尝试获取 Lock1)时,FirstThread 已经获取了 Lock1 的锁定。这就会导致经典的死锁情形。从这种情况中恢复的唯一方法是重新启动 JVM。
上方代码中捕获的线程转储文件将会变成下面这样:
"Thread-1" prio=6 tid=0x0000000007319000 nid=0x7cd3c waiting for monitor entry [0x0000000008a3f000]
java.lang.Thread.State: BLOCKED (on object monitor)
at com.tier1app.DeadLockSimulator$SecondThread.run(DeadLockSimulator.java:29)
- waiting to lock 0x00000007ac3b1970 (a java.lang.Object)
- locked 0x00000007ac3b1980 (a java.lang.Object)
Locked ownable synchronizers:
- None
"Thread-0" prio=6 tid=0x0000000007318800 nid=0x7da14 waiting for monitor entry [0x000000000883f000]
java.lang.Thread.State: BLOCKED (on object monitor)
at com.tier1app.DeadLockSimulator$FirstThread.run(DeadLockSimulator.java:16)
- waiting to lock 0x00000007ac3b1980 (a java.lang.Object)
- locked 0x00000007ac3b1970 (a java.lang.Object)
Locked ownable synchronizers:
- None
Leave a Reply