试验书上的一段死锁代码,但是一直处于锁等待状态,理论上过了一会儿应该会抛异常的,为什么会这样?
代码如下
public class DeadLockDemo {
private static String A = "A";
private static String B = "B";
public static void main(String[] args) {
new DeadLockDemo().deadLock();
}
private void deadLock() {
Thread t1 = new Thread(new Runnable() {
@Override
public void run() {
synchronized (A) {
try {
Thread.currentThread().sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (B) {
System.out.println("1");
}
}
}
});
Thread t2 = new Thread(new Runnable() {
@Override
public void run() {
synchronized (B) {
synchronized (A) {
System.out.println("2");
}
}
}
});
t1.start();
t2.start();
}
}
1
nifury 2021-05-02 01:04:29 +08:00
Java 不检测 deadlock 的吧?为什么要抛异常?
|
2
monstervivi 2021-05-02 02:12:56 +08:00 1
死锁的定义:[死锁是指两个或两个以上的进程在执行过程中,由于竞争资源或者由于彼此通信而造成的一种阻塞的现象。]( https://baike.baidu.com/item/%E6%AD%BB%E9%94%81)
所以样式代码中的情况可能是: 1. 线程 t1 在第一个 synchronize block 中持有 String A monitor; 2. 线程 t1 sleep 2 秒; 3. 线程 t2 在第一个 synchronize block 中持有 String B monitor; 4. 线程 t2 在第二个 synchronize block 中需要获得 String A monitor,但此时的 String A monitor 被线程 t1 所持有,所以等待线程 t1 释放 String A monitor 。(如果是 JDK 6 以上,会进行锁膨胀,因为优化了 synchronize ) 5. 线程 t1 sleep 2 秒后,进入第二个 synchronize block,此 block 需要获取 String B monitor,但此时的 String B monitor 被线程 t2 所持有,所以等待线程 t2 释放 String B monitor 。 6. 所以形成了死锁。 可以通过以下的方式,查看 DeadLock 的具体信息 1. 查看 DeadLockDemo 的程序 pid ```bash jps ``` 响应如下: ```bash 11094 DeadLockDemo 11100 Jps ``` 2. 查看 DeadLockDemo 程序的 dump 信息 ```bash jstack -l 11094 ``` 可以看到最后的结果如下: ```bash Found one Java-level deadlock: ============================= "Thread-1": waiting to lock monitor 0x00007fe08201aab8 (object 0x000000076aba4500, a java.lang.String), which is held by "Thread-0" "Thread-0": waiting to lock monitor 0x00007fe08201bea8 (object 0x000000076aba4530, a java.lang.String), which is held by "Thread-1" ``` |
3
monstervivi 2021-05-02 02:18:40 +08:00
上面回复中的「所以样式代码中的情况可能是:」少说了一点:7. 所以程序没有正常地结束。
|
4
0576coder OP |