2012-07-04 131 views
2

考慮你有以下代碼:
1.爲什麼我們使用雙重鎖定,爲什麼單鎖不夠好,請提供詳細的例子。
2.這個實現的主要缺點是什麼?我該如何證明它?
謝謝。單雙鎖設計模式

public sealed class SomeSingleton5 
{ 
    private static SomeSingleton5 s_Instance = null; 
    private static object s_LockObj = new Object(); 

    private SomeSingleton5() { } 

    public static SomeSingleton5 Instance 
    { 
     get 
     { 
      if (s_Instance == null) 
      { 
       lock (s_LockObj) 
       { 
        if (s_Instance == null) 
        { 
         s_Instance = new SomeSingleton5(); 
        } 
       } 
      } 

      return s_Instance; 
     } 
    } 
} 
+0

在.NET中你不必使用這種模式。類型系統保證靜態字段不會受到雙重鎖定模式嘗試避免的爭用條件的影響。在Java中它是不同的。 –

+1

第二個檢查是在's_Instance'初始化之前處理一個競態條件,兩個線程都訪問getter。兩個線程都將's_Instance'評估爲null,所以_both_進入鎖定狀態。人們將進入,初始化's_Instance'並返回。第二個線程將進入,如果你沒有第二個檢查,它會_reinitialize_'s_Instance'並返回一個新的實例。現在這兩個線程將有兩個不同的單例實例。 –

+0

@ChrisSinclair:好的,現在很明顯,但我現在想知道這個解決方案是否可以完全解決任何競爭條件,或者我們剛剛解決了您提到的特定情況。我找不到能夠映射所有可能發生的競爭條件,因此很難理解爲什麼這能夠解決所有競爭條件 – JavaSa

回答

7

我覺得單例類的最好的實現是由Jon Skeet提供。

public sealed class Singleton 
{ 
    private static readonly Singleton instance = new Singleton(); 
    public static Singleton Instance { get { return instance; } } 
    static Singleton() {} 
    private Singleton() {} 
} 

Singleton by Jon Skeet Clarification

+1

這確實是最好的方法。不需要鎖定。唯一需要的是,必須使用空白的靜態構造函數。 – Tilak

+0

+1靜態初始化確實是一個非常有效的系統:) – leppie

+0

@Tilak:爲什麼需要一個空白的靜態構造函數?編輯:沒關係,在鏈接中找到答案:) – leppie

2
  1. Aquiring鎖是昂貴的。如果沒有第一個if(s_Instance == null)檢查,鎖定將被獲取每個有人訪問單身人士。但實際上只需要在實例創建時出現鎖定。所以第一個if(s_Instance == null)可以防止不必要的鎖定。第二個if(s_Instance == null)需要在那裏,因爲最初兩個線程可能已經將第一個if(s_Instance == null)評估爲true,並且之後這兩個線程將在鎖之內彼此連續地實例化s_Instance
  2. 我在你的實現中沒有看到任何實際的缺點,但使用替代方法(靜態構造函數,請參見下文),我們有一個更簡單,代碼更少的解決方案。所以它更容易維護,錯誤率更低。而且它根本不需要鎖定。如前所述,鎖定是昂貴的。

您可以通過使用一個靜態構造函數改進:

public sealed class SomeSingleton5 
{ 
    // the compiler will generate a static constructor containing the following code 
    // and the CLR will call it (once) before SomeSingleton5 is first acccessed 
    private static SomeSingleton5 s_Instance = new SomeSingleton5(); 

    private SomeSingleton5() { } 

    public static SomeSingleton5 Instance 
    { 
     get 
     { 
      return s_Instance; 
     } 
    } 
} 
+0

謝謝,但關於我的實現,爲什麼我們要做雙重檢查(ifX2),我真的不明白它的目的 – JavaSa

+0

我已經更新了我的答案。現在有意義嗎? – bitbonk