1. 程式人生 > >19、多執行緒的死鎖

19、多執行緒的死鎖

在多執行緒系列文章第一篇中我們講解到了死鎖的概念。

由上圖可知,死鎖就是多個執行緒都在等待對方釋放自己所需要的鎖。 我們知道機器不像我們人這麼的謙讓,他們都是搶佔資源跑任務的。所以“你若不釋放,我打死也不會釋放。”

下面的例子演示了死鎖。

package com.demo3;

public class MyObject implements Runnable {

    private Object lock = new Object();
    private Object lock2 = new Object();
    private Object lock3 = new Object();

    @Override
    public void run() {
        if (Thread.currentThread().getName().equals("A")) {
            synchronized (lock) {
                try {
                    System.out.println("執行緒A拿到lock");
                    Thread.sleep(3000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                synchronized (lock2) {
                    System.out.println("執行緒A拿到lock2");
                }
            }
        }
        if (Thread.currentThread().getName().equals("B")) {
            synchronized (lock2) {
                try {
                    System.out.println("執行緒B拿到lock2");
                    Thread.sleep(3000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                synchronized (lock3) {
                    System.out.println("執行緒B拿到lock3");
                }
            }
        }
        if (Thread.currentThread().getName().equals("C")) {
            synchronized (lock3) {
                try {
                    System.out.println("執行緒C拿到lock3");
                    Thread.sleep(3000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                synchronized (lock) {
                    System.out.println("執行緒C拿到lock");
                }
            }
        }
    }
}
package com.demo3;

public class Run {
    public static void main(String[] args) {
        MyObject myObject = new MyObject();
        Thread threadA = new Thread(myObject,"A");
        Thread threadB = new Thread(myObject,"B");
        Thread threadC = new Thread(myObject,"C");
        threadA.start();
        threadB.start();
        threadC.start();
    }
}

執行結果:

執行緒A拿到lock
執行緒B拿到lock2
執行緒C拿到lock3

abc,執行緒拿到 lock lock2 lock3之後,就再也沒有釋放鎖,來達到交、交換鎖,執行後續程式碼的情況。這也就是死鎖。為了進一步驗證我們的判斷,我們使用terminal命令列來檢視:

F:\daydayup\thread-demo>jps
11952 Launcher
1348 Run
8740
7084 Jps
F:\daydayup\thread-demo>jstack -l 1348
2018-12-22 15:19:55
Full thread dump Java HotSpot(TM) 64-Bit Server VM (25.31-b07 mixed mode):
......
Java stack information for the threads listed above:
===================================================
"C":
        at com.demo3.MyObject.run(MyObject.java:46)
        - waiting to lock <0x00000000d732d6c0> (a java.lang.Object)
        - locked <0x00000000d732d6e0> (a java.lang.Object)
        at java.lang.Thread.run(Thread.java:745)
"A":
        at com.demo3.MyObject.run(MyObject.java:20)
        - waiting to lock <0x00000000d732d6d0> (a java.lang.Object)
        - locked <0x00000000d732d6c0> (a java.lang.Object)
        at java.lang.Thread.run(Thread.java:745)
"B":
        at com.demo3.MyObject.run(MyObject.java:33)
        - waiting to lock <0x00000000d732d6e0> (a java.lang.Object)
        - locked <0x00000000d732d6d0> (a java.lang.Object)
        at java.lang.Thread.run(Thread.java:745)

Found 1 deadlock.

有輸出結果足以驗證死鎖的產生。我們在日常工作中,應該避免死鎖。