懒惰的线程安全 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) 检查完成两次:一次获取锁定之前,一次之后。即使没有第一次空检查,此实现仍然是线程安全的。但是,这意味着每次请求实例都会获取锁,这会导致性能受损。添加第一个空检查,以便除非必要,否则不会获取锁定。第二次空检查确保只有第一个获取锁的线程才会创建实例。其他线程将找到要填充的实例并向前跳过。