2012-04-28 62 views
15

我在Heinz Kabutz的Java專家通訊版本中看到了這一點,儘管Kabutz博士的其他(甚至全部)文章都有詳細解釋和詳細說明,但他似乎掩蓋了這是什麼代碼做什麼,或者更重要的是,它的意義是什麼:Java:嵌套同步塊

public class SomeObject { 
    private Object lock1; 
    private Object lock2; 

    public void doSomething() { 
     synchronized(lock1) { 
      synchronized(lock2) { 
       // ... 
      } 
     } 
    } 
} 

什麼是嵌套​​塊的含義是什麼?這是如何影響嘗試doSomething()的不同線程?

+0

在這種情況下,所有線程都會在外鎖處被阻塞,直到它被內鎖中的線程釋放。 – 2012-04-28 15:56:02

+2

你發佈的snippit沒有做任何事情;唯一可以擁有'lock2'的線程是擁有'lock1'的線程。不知道代碼的其餘部分是什麼以及這些鎖被用於什麼,這是不可能回答的。 – 2012-04-28 15:56:48

+0

你在閱讀哪篇文章? – Jeffrey 2012-04-28 16:00:38

回答

27

有2個是一個必須注意

  1. 嵌套鎖定可能導致死鎖非常容易,如果一個正在使用的等待/通知可能出現的問題。這是對原因的解釋。 http://tutorials.jenkov.com/java-concurrency/nested-monitor-lockout.html

  2. 每個人都應該警惕,如果另一種方法希望鎖定兩個相同的對象,它們必須始終做到以相同的順序,否則就在這篇文章解釋了另一種死鎖情況的可能性:How to avoid Nested synchronization and the resulting deadlock

+1

請問是否有任何解決方案嵌套監視器鎖定?是否可以在內部鎖和外部鎖上調用wait,或者沒有辦法做到這一點? – 2014-03-22 10:19:54

+0

死鎖需要4個先決條件。互斥(同步(節點){同步(邊緣){}},而另一個函數具有同步(邊緣){同步(節點){}}),不可搶佔,循環等待和資源保持。只有相互排斥纔會導致僵局。如果你好奇,這些被稱爲科夫曼條件。 HTTP://en.wikipedia。組織/維基/ Deadlock_prevention_algorithms – 2014-09-25 21:14:42

1

本身這段代碼不會引起任何問題。 但是如果存在類似這樣的代碼,問題可能會以死鎖的形式出現;我們有兩種方法,如果有多個線程試圖訪問這些方法則有可能是因爲嵌套同步塊的僵局對象被鎖定在對面的訂單 -

public void doSomething() { 
    synchronized(lock1) { 
     synchronized(lock2) { 
      // ... 
     } 
    } 
} 

public void doOtherthing() { 
    synchronized(lock2) { 
     synchronized(lock1) { 
      // ... 
     } 
    } 
} 

現在以這樣的方式同步塊。

0

根據Nested Monitor Lockout Tutorial

在嵌套監視器閉鎖,線程1持有鎖A,以及用於從線程的信號等待 2.線程2所需要的鎖甲發送 信號主題1 。當處於死鎖狀態時,兩個線程正在等待對方釋放鎖。

死鎖可能類似於兩個人被關押在兩個房間,他們想切換到另一個房間,但他們都只有對方的鑰匙。儘管嵌套顯示器鎖定就像老闆一樣安排在房間裏睡覺,並假設只有當某人進入房間時纔會被喚醒。而祕書負責喚醒他的老闆。但老闆在睡覺時仍然握着房間的鑰匙,所以祕書不能進來把他叫醒。