JAVA多線程——死鎖分析

線程死鎖的原因:當兩個或多個線程正在等待對方佔有的鎖,死鎖就會發生

死鎖會導致兩個線程無法繼續運行,被永遠掛起。


簡單的死鎖例子

創建兩個互相等待對方釋放鎖的線程

public class DeadLock1 implements Runnable {

    private Object o1, o2;

    public DeadLock1(Object o1, Object o2) {
        this.o1 = o1;
        this.o2 = o2;
    }

    @Override
    public void run() {
        fun();
    }

    public void fun() {
        //獲取o1的monitor
        synchronized (o1) {
            try {
                TimeUnit.MILLISECONDS.sleep(500);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            //獲取o2的monitor
            synchronized (o2) {

            }
        }
    }

}

public class DeadLock2 implements Runnable {

    private Object o1, o2;

    public DeadLock2(Object o1, Object o2) {
        this.o1 = o1;
        this.o2 = o2;
    }

    @Override
    public void run() {
        fun();
    }

    public void fun() {
        //獲取o2的monitor
        synchronized (o2) {
            try {
                TimeUnit.MILLISECONDS.sleep(500);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            //獲取o1的monitor
            synchronized (o1) {

            }
        }
    }

}

創建測試類

public class TestDeadLock {

    public static void main(String[] args) {
        Object lockObj1 = new Object();
        Object lockObj2 = new Object();
        //分別啓動兩個線程
        Thread thread1 = new Thread(new DeadLock1(lockObj1, lockObj2));
        thread1.start();
        Thread thread2 = new Thread(new DeadLock2(lockObj1, lockObj2));
        thread2.start();
    }

}

運行並打印堆棧信息:

Found one Java-level deadlock:
=============================
"Thread-1":
  waiting to lock monitor 0x0000000054a4d6b8 (object 0x00000000eb540e20, a java.lang.Object),
  which is held by "Thread-0"
"Thread-0":
  waiting to lock monitor 0x0000000054a4c218 (object 0x00000000eb540e30, a java.lang.Object),
  which is held by "Thread-1"

Java stack information for the threads listed above:
===================================================
"Thread-1":
	at zj.test.deadlock.DeadLock2.fun(DeadLock2.java:33)
	- waiting to lock <0x00000000eb540e20> (a java.lang.Object)
	- locked <0x00000000eb540e30> (a java.lang.Object)
	at zj.test.deadlock.DeadLock2.run(DeadLock2.java:19)
	at java.lang.Thread.run(Thread.java:745)
"Thread-0":
	at zj.test.deadlock.DeadLock1.fun(DeadLock1.java:33)
	- waiting to lock <0x00000000eb540e30> (a java.lang.Object)
	- locked <0x00000000eb540e20> (a java.lang.Object)
	at zj.test.deadlock.DeadLock1.run(DeadLock1.java:19)
	at java.lang.Thread.run(Thread.java:745)

Found 1 deadlock.

線程0想要lock <0x00000000eb540e30>
線程1想要
lock <0x00000000eb540e20> 

雙方都在等待對方釋放鎖




對於真正的死鎖而言,虛擬機從鎖的持有和請求情況就能判斷出來,因此打印堆棧時虛擬機會自動給出死鎖的提示


許多人把系統無響應的問題統稱爲死鎖,這種稱爲是不恰當的

真正意義上的死鎖是由於代碼引入的錯誤而導致的死鎖

 

要想從死鎖中恢復臨時也是唯一的規避辦法是將系統重啓,然後趕快去修改導致這個死鎖的BUG

能否及時發現死鎖,依賴於你的運氣和你準備的測試用例的有效性

 tips:死鎖的兩個或多個線程是不消耗CPU的








發佈了39 篇原創文章 · 獲贊 12 · 訪問量 6萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章