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