V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
0576coder
V2EX  ›  程序员

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

  •  
  •   0576coder · 2021-05-02 00:33:37 +08:00 · 1656 次点击
    这是一个创建于 1083 天前的主题,其中的信息可能已经有所发展或是发生改变。

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

    代码如下

    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();
        }
    }
    
    4 条回复    2021-05-02 09:24:03 +08:00
    nifury
        1
    nifury  
       2021-05-02 01:04:29 +08:00
    Java 不检测 deadlock 的吧?为什么要抛异常?
    monstervivi
        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"
    ```
    monstervivi
        3
    monstervivi  
       2021-05-02 02:18:40 +08:00
    上面回复中的「所以样式代码中的情况可能是:」少说了一点:7. 所以程序没有正常地结束。
    0576coder
        4
    0576coder  
    OP
       2021-05-02 09:24:03 +08:00
    @monstervivi

    感谢大佬
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   1090 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 25ms · UTC 22:57 · PVG 06:57 · LAX 15:57 · JFK 18:57
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.