2013-07-16 206 views
-1

第8行或16行如何發生死鎖?同步中的死鎖

1. public class DeadlockRisk { 
2. private static class Resource { 
3.  public int value; 
4. } 
5. private Resource resourceA = new Resource(); 
6. private Resource resourceB = new Resource(); 
7. public int read() { 
8.  synchronized(resourceA) { 
9.  synchronized(resourceB) { 
10.   return resourceB.value + resourceA.value; 
11.  } 
12.  } 
13. } 
14 
15. public void write(int a, int b) { 
16.  synchronized(resourceB) { 
17.  synchronized(resourceA) { 
18.   resourceA.value = a; 
19.   resourceB.value = b; 
20.  } 
21.  } 
22. } 
23. } 
+1

沒有死鎖,因爲讀取和寫入不會被調用:-) –

+0

當線程讀取鎖定資源A時,*同時*線程寫入鎖定資源B,因此兩個線程都無法鎖定下一個資源,因爲它們彼此鎖定: ) – 2013-07-16 13:57:25

回答

5

死鎖可能會發生,因爲鎖定順序是不一致的,這意味着一個線程已經獲得resourceAresourceB等待另一個線程已獲得resourceB,但正在等待resourceA。例如:

  • T1調用read(),成功獲取resourceA,然後暫停。
  • T2呼叫write(),成功獲取resourceB並等待resourceA
  • T1重新開始,正在等待resourceB(永遠不會被T2釋放)。

T1T2都不能進步,因爲每個人都在等待其他人鎖定的資源。總是要有一個一致的鎖順序:(然而,在張貼的代碼似乎沒有理由有多個鎖,因爲這兩個鎖總是收購)

public int read() { 
    synchronized(resourceA) { 
     synchronized(resourceB) { 

public void write() { 
    synchronized(resourceA) { 
     synchronized(resourceB) { 

+0

他剛剛那樣做了。目前還不清楚你在這裏尋找什麼樣的答案。在任何情況下都是一樣的。如果您以不一致的順序獲取鎖,則可能會導致死鎖。 – EJP

0

閱讀獲得resourceA作爲的一部分外鎖。寫入獲取resourceB。這發生在任一線程鎖定內部鎖的對象之前。

要繼續,讀取需要resourceB,但寫入已經有了resourceB。寫入可以在獲得resourceA時立即釋放resourceB,但讀取具有resourceA並且只有在給予resourceB時才能放棄。

作爲一般技巧,鎖定多個對象時使用一致的順序。 A和B中的任何一個,或者B,然後兩者都是A.

+0

感謝您的答案和建議,以避免在這種情況下的死鎖... –

+1

@BlueDiamond閱讀最後一句。 – hexafraction