2015-08-17 68 views
1

指的這個https://en.wikipedia.org/wiki/Double-checked_locking, 我們:爲什麼在雙重檢查鎖定中添加第二個測試?

// "Double-Checked Locking" idiom 
class Foo { 
    private Helper helper; 
    public Helper getHelper() { 
     if (helper == null) { 
      synchronized(this) { 
       if (helper == null) { 
        helper = new Helper(); 
       } 
      } 
     } 
     return helper; 
    }  
    // other functions and members... 
} 

什麼是第二次測試的目的是什麼? 2個線程是否可以同時訪問同一臨界區?

回答

4

兩個線程不能同時訪問同一臨界區;根據定義,關鍵部分是相互排斥的。

要回答你的問題,第一個null測試是一個沒有同步的便宜測試,第二個測試用同步檢查實際狀態。


第二個測試是必要的。假設我們沒有它,看着這樣的代碼:

public Helper getHelper() { 
    if (helper == null) { 
     synchronized(this) { 
      helper = new Helper(); 
     } 
    } 
    return helper; 
} 

假設線程A執行if (helper == null)和它測試true,所以它進入if塊,但執行被中止。沒有變量尚未更新。

然後線程B執行if (helper == null)並且它測試true,所以它進入if塊。然後它繼續執行到​​塊並初始化helper對象並返回。

現在線程A繼續執行,進入​​塊,用新對象覆蓋helper,並返回該對象。

我們現在的問題是helper被初始化了兩次,有不同的對象。

這就是爲什麼第二次測試是必要的。

+0

OK now i得到它,謝謝你,你很清楚 –

+4

只是爲了避免有人簡單地複製OP的代碼:它是**不是100%正確**,[wiki](https://en.wikipedia.org/ wiki/Double-checked_locking)表示您必須將變量聲明爲volatile,或者使用[按需求持有人慣用法初始化](https://en.wikipedia.org/wiki/Initialization_on_demand_holder_idiom)或包裝器。 – beosign

+0

@jameslarge:你的論點的問題是,在線程B可見對象的字段之前,線程B可以看到變量'helper' - 因爲沒有發生 - 在涉及關係之前。因此'volatile'限定符*是必需的。 – Nayuki

2

爲了使它更加明顯會發生什麼,考慮下面的代碼:

if (helper == null) { 
    Thread.sleep(1000); 
    synchronized(this) { 
     if (helper == null) { 
      helper = new Helper(); 
     } 
    } 
} 

這僅僅是一個例子,所以我不關心InterruptedException

應該清楚的是,在通過第一次測試和進入關鍵區域之間,還有一段時間需要其他線程進入並首先進入關鍵區域。

0

除了所有其他答案,一個非常好的例子是線程安全Singleton模式。你又在相同的:

public static Singleton getInstanceDC() { 
    if (_instance == null) {  // Single Checked 
    synchronized (Singleton.class) { 
     if (_instance == null) { // Double checked 
       _instance = new Singleton(); 
      } 
    } 
    } 
    return _instance; 
} 

所以基本上進行加鎖,如果相比指針檢查instance != null是貴了不少。該實現還必須確保在Singleton初始化時,不會有線程爭用條件導致的問題。所以主要原因是表現。如果instance != null(第一次除外),則不需要執行昂貴的鎖定:同時訪問初始化單例的兩個線程將被不必要地同步。這張照片展示了明確:

enter image description here

有很多more in Singletons然後就雙重校驗:

  • 早期和延遲實例化的單例模式

  • 辛格爾頓和系列化

相關問題