線程死鎖的原因:當兩個或多個線程正在等待對方佔有的鎖,死鎖就會發生
死鎖會導致兩個線程無法繼續運行,被永遠掛起。
簡單的死鎖例子
創建兩個互相等待對方釋放鎖的線程
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的