死鎖的原因
首先,產(chǎn)生死鎖需要兩個鎖對象(假設(shè)A,B),兩個線程同時運行,并使用兩個鎖對象。簡單的說就是鎖A等待鎖B釋放,而鎖B等待鎖A釋放,這樣就產(chǎn)生了所謂的死鎖。當(dāng)然產(chǎn)生死鎖的機率并不是100%,而是有一定的機率;原因是CPU在線程之間切換是沒有規(guī)律的,所以產(chǎn)生死鎖,具體看CPU的調(diào)度。請看下面實現(xiàn)代碼,再進一步剖析:
public class DieLock {
public static final Object LOCK_A = new Object();
public static final Object LOCK_B = new Object();
public static void main(String[] args) {
// 線程一
new Thread(() ->{
System.out.println("Thread a starter");
synchronized (LOCK_A) {
System.out.println("Thread a: into lock a!");
synchronized (LOCK_B) {
System.out.println("Thread a: into lock b!");
}
System.out.println("Thread a: release lock b!");
}
System.out.println("Thread a: release lock a!");
}).start();
// 線程二
new Thread(() ->{
System.out.println("Thread b starter");
synchronized (LOCK_B) {
System.out.println("Thread b: into lock b!");
synchronized (LOCK_A) {
System.out.println("Thread b: into lock a!");
}
System.out.println("Thread b: release lock a!");
}
System.out.println("Thread b: release lock b!");
}).start();
}
}
分析
首先定義兩個鎖對象,在java中所有對象都可以做鎖對象,這里選擇Object:LOCK_A,LOCK_B。
啟動了兩個線程,兩個線程中都有兩個同步鎖,第一個是鎖B在鎖A的里面,第二個是鎖A在鎖B的里面,就是兩個鎖交叉使用。也就是兩個同步代碼塊,在執(zhí)行進入到代碼塊時,鎖對象已經(jīng)被鎖住,代碼塊執(zhí)行完鎖對象釋放。
-
大家都知道CPU在線程之間隨機快速切換,我們分析這段代碼看出現(xiàn)死鎖的情況:
- 當(dāng)?shù)谝粋€線程執(zhí)行到第一個同步代碼塊時,LOCK_A對象已經(jīng)被鎖?。籆PU快速切換到第二個線程,執(zhí)行第一個代碼塊LOCK_B對象被鎖住。
- CPU又切回到第一個線程,程序繼續(xù)執(zhí)行,第一個線程現(xiàn)在要執(zhí)行第二個同步代碼塊,此時程序中LOCK_B對象已經(jīng)被鎖住,無法往下面執(zhí)行;CPU切換到線程二,同理往下執(zhí)行,而LOCK_A也被鎖住了。此時:兩個線程相互等待對方的鎖釋放,兩邊都釋放不了,就是產(chǎn)生了死鎖現(xiàn)象。
以上是個人拙見,若有不對之處,感謝指正,感謝閱讀.