C 示例多執行緒單例

靜態初始化適用於大多數情況。當你的應用程式必須延遲例項化,使用非預設建構函式或在例項化之前執行其他任務,並在多執行緒環境中工作時,你需要一個不同的解決方案。但是,確實存在這樣的情況,在這種情況下,你不能依賴公共語言執行庫來確保執行緒安全,如靜態初始化示例中所示。在這種情況下,你必須使用特定的語言功能來確保在存在多個執行緒的情況下只建立一個物件例項。一種比較常見的解決方案是使用 Double-Check Locking [Lea99]慣用法來保持單獨的執行緒不會同時建立單例的新例項。

以下實現僅允許單個執行緒進入關鍵區域,當沒有建立 Singleton 例項時,鎖定塊會識別該關鍵區域:

using System;

public sealed class Singleton {    
   private static volatile Singleton instance;    
   private static object syncRoot = new Object();

   private Singleton() {}

   public static Singleton Instance    {
      get 
      {
         if (instance == null) 
         {
            lock (syncRoot) 
            {
               if (instance == null) 
                  instance = new Singleton();
            }
         }

         return instance;
      }    
  } 
}

此方法確保僅建立一個例項,並且僅在需要例項時才實現。此外,該變數被宣告為 volatile,以確保在訪問例項變數之前完成對例項變數的賦值。最後,這種方法使用 syncRoot 例項來鎖定,而不是鎖定型別本身,以避免死鎖。

這種雙重檢查鎖定方法解決了執行緒併發問題,同時避免了每次呼叫 Instance 屬性方法時的獨佔鎖定。它還允許你延遲例項化,直到首次訪問該物件。實際上,應用程式很少需要這種型別的實現。在大多數情況下,靜態初始化方法就足夠了。

參考:MSDN

致謝

[Gamma95] Gamma,Helm,Johnson 和 Vlissides。設計模式:可重用物件導向軟體的元素。Addison-Wesley,1995 年。

[Lea99] Lea,Doug。Java 中的併發程式設計,第二版。艾迪生 - 韋斯利,1999 年。

[Sells03]賣,克里斯。 “密封糟透了。” sellsbrothers.com 新聞。可在以下網址獲得: http//www.ussellsbrothers.com/news/showTopic.aspx?xTto = 411