懶惰的執行緒安全 Singleton(使用雙重鎖定)

在 .NET 的早期版本中,這種執行緒安全版本的單例是必需的,其中 static 初始化不保證是執行緒安全的。在框架的更現代版本中,通常首選靜態初始化單例, 因為在以下模式中很容易出現實現錯誤。

public sealed class ThreadSafeSingleton
{
   private static volatile ThreadSafeSingleton instance;
   private static object lockObject = new Object();

   private ThreadSafeSingleton()
   {
   }

   public static ThreadSafeSingleton Instance
   {
      get 
      {
         if (instance == null) 
         {
            lock (lockObject) 
            {
               if (instance == null)
               {
                  instance = new ThreadSafeSingleton();
               }
            }
         }

         return instance;
      }
   }
}

請注意,if (instance == null) 檢查完成兩次:一次獲取鎖定之前,一次之後。即使沒有第一次空檢查,此實現仍然是執行緒安全的。但是,這意味著每次請求例項都會獲取鎖,這會導致效能受損。新增第一個空檢查,以便除非必要,否則不會獲取鎖定。第二次空檢查確保只有第一個獲取鎖的執行緒才會建立例項。其他執行緒將找到要填充的例項並向前跳過。