为什么这段书本上的 Java 死锁代码执行的时候我一直处于锁等待状态

2021-05-02 00:33:37 +08:00
 0576coder

试验书上的一段死锁代码,但是一直处于锁等待状态,理论上过了一会儿应该会抛异常的,为什么会这样?

代码如下

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();
    }
}
1761 次点击
所在节点    程序员
4 条回复
nifury
2021-05-02 01:04:29 +08:00
Java 不检测 deadlock 的吧?为什么要抛异常?
monstervivi
2021-05-02 02:12:56 +08:00
死锁的定义:[死锁是指两个或两个以上的进程在执行过程中,由于竞争资源或者由于彼此通信而造成的一种阻塞的现象。]( 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"
```
monstervivi
2021-05-02 02:18:40 +08:00
上面回复中的「所以样式代码中的情况可能是:」少说了一点:7. 所以程序没有正常地结束。
0576coder
2021-05-02 09:24:03 +08:00
@monstervivi

感谢大佬

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/774573

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX