死鎖是這樣一種情形:多個線程同時被阻塞,它們中的一個或者全部都在等待某個資源被釋放。由於線程被無限期地阻塞,因此程序不可能正常終止。
導致死鎖的根源在於不適當地運用“synchronized”關鍵詞來管理線程對特定對象的訪問。“synchronized”關鍵詞的作用是,確保在某個時刻只有一個線程被允許執行特定的代碼塊,因此,被允許執行的線程首先必須擁有對變量或對象的排他性的訪問權。當線程訪問對象時,線程會給對象加鎖,而這個鎖導致其它也想訪問同一對象的線程被阻塞,直至第一個線程釋放它加在對象上的鎖。
由於這個原因,在使用“synchronized”關鍵詞時,很容易出現兩個線程互相等待對方做出某個動作的情形。代碼一是一個導致死鎖的簡單例子。
package com.thread;
public class TestThread13 {
public static void main(String[] args) {
DeadLock t1 = new DeadLock();
DeadLock t2 = new DeadLock();
t1.flag = 1;
t2.flag = 0;
new Thread(t1).start();
new Thread(t2).start();
}
}
class DeadLock implements Runnable{
public int flag = 1 ;
static Object o1 = new Object(), o2 = new Object();
public void run() {
System.out.println("flag :"+flag);
if (flag == 1) {
synchronized (o1) {
System.out.println(Thread.currentThread().getName()+" o1 locked");
try{Thread.sleep(500);}catch(Exception e){e.printStackTrace();}
synchronized (o2) {
System.out.println(Thread.currentThread().getName()+" o2 locked");
System.out.println("1");
}
}
}
if (flag == 0) {
synchronized (o2) {
System.out.println(Thread.currentThread().getName()+" o2 locked");
try{Thread.sleep(500);}catch(Exception e){e.printStackTrace();}
synchronized (o1) {
System.out.println(Thread.currentThread().getName()+" o1 locked");
System.out.println("0");
}
}
}
}
}
運行結果:
分析:t1線程啓動了,但並沒有打印“1”;t2線程啓動了,但並沒有打印"0".因爲2個線程啓動後都阻塞了。
說明: t1線程啓動後,佔領監視器o1後,休眠500毫秒,這時t2線程佔領了監視器o2,從此以後程序就堵塞了。正如截圖結果。
原因是,t1線程佔有監視器o1,等待t2線程釋放監視器o2;同時,t2線程佔有監視器o2,等待t1線程釋放監視器o1, t1和t2這兩個線程都在等對方先釋放監視器,結果誰都不先釋放,所以2個線程會一直堵塞。t1線程不能繼續執行打印"1", t2線程不能繼續執行打印“0”。