死鎖
死鎖是這樣一種情形:多個線程同時被阻塞,它們中的一個或者所有都在等待某個資源被釋放。因爲線程被無限期地阻塞,所以程序不可能正常終止。
致使死鎖的根源在於不適當地運用「synchronized」關鍵詞來管理線程對特定對象的訪問。「synchronized」關鍵詞的做用是,確保在某個時刻只有一個線程被容許執行特定的代碼塊,所以,被容許執行的線程首先必須擁有對變量或對象的排他性的訪問權。當線程訪問對象時,線程會給對象加鎖,而這個鎖致使其它也想訪問同一對象的線程被阻塞,直至第一個線程釋放它加在對象上的鎖。
因爲這個緣由,在使用「synchronized」關鍵詞時,很容易出現兩個線程互相等待對方作出某個動做的情形。代碼一是一個致使死鎖的簡單例子。
//代碼一 多線程
1 class Deadlocker { 2 int field_1; 3 private Object lock_1 = new int[1]; 4 int field_2; 5 private Object lock_2 = new int[1]; 6 7 public void method1(int value) { 8 「synchronized」 (lock_1) { 9 「synchronized」 (lock_2) { 10 field_1 = 0; field_2 = 0; 11 } 12 } 13 } 14 15 public void method2(int value) { 16 「synchronized」 (lock_2) { 17 「synchronized」 (lock_1) { 18 field_1 = 0; field_2 = 0; 19 } 20 } 21 } 22 } 23
參考代碼一,考慮下面的過程:
◆ 一個線程(ThreadA)調用method1()。
◆ ThreadA在lock_1上同步,但容許被搶先執行。
◆ 另外一個線程(ThreadB)開始執行。
◆ ThreadB調用method2()。
◆ ThreadB得到lock_2,繼續執行,企圖得到lock_1。但ThreadB不能得到lock_1,由於ThreadA佔有lock_1。
◆ 如今,ThreadB阻塞,由於它在等待ThreadA釋放lock_1。
◆ 如今輪到ThreadA繼續執行。ThreadA試圖得到lock_2,但不能成功,由於lock_2已經被ThreadB佔有了。
◆ ThreadA和ThreadB都被阻塞,程序死鎖。
固然,大多數的死鎖不會這麼顯而易見,須要仔細分析代碼才能看出,對於規模較大的多線程程序來講尤爲如此。好的線程分析工具,例如JProbe Threadalyzer可以分析死鎖並指出產生問題的代碼位置。 工具