单例模式:进程唯一。

单例模式:进程唯一。

  • 非线程安全。

    public sealed class SingletonV1
    {
        private static SingletonV1 instance = null;
    
        private SingletonV1()
        {
        }
    
        public static SingletonV1 Instance
        {
            get
            {
                if (instance == null) // -> 1
                { // -> 2
                    instance = new SingletonV1();
                }
    
                return instance;
            }
        }
    }
    

    假设:首次访问,同一时间,有N(N>=2)个线程同时访问单例。

    解:

    1. 实例并未创建,所有线程都能进入创建实例代码块。
    2. N个线程使用的实例不相同。

    注:违反了单例的唯一性原则。

  • 简单线程安全。

    public sealed class SingletonV2
    {
        private static SingletonV2 instance = null;
        private static readonly object padlock = new object();
    
        SingletonV2()
        {
        }
    
        public static SingletonV2 Instance
        {
            get
            {
                lock (padlock) // -> 1
                {
                    if (instance == null)
                    {
                        instance = new SingletonV2();
                    }
                    return instance;
                }
            }
        }
    }
    

    假设:同一时间,有N(N>=2)个线程同时访问单例。

    解:由于lock是悲观锁,导致获取单例变成了单线程操作。

    注:单线程的代码块,会严重降低多线程的性能。

  • 双重检查线程安全。

    public sealed class SingletonV3
    {
        private static SingletonV3 instance = null;
        private static readonly object padlock = new object();
    
        SingletonV3()
        {
        }
    
        public static SingletonV3 Instance
        {
            get
            {
                if (instance == null) // -> 1
                {
                    lock (padlock)
                    {
                        if (instance == null) // -> 2
                        {
                            instance = new SingletonV3();
                        }
                    }
                }
                return instance;
            }
        }
    }
    

    解:

    1. 第一层检查的意义:当实例被创建后,不再进入锁。
    2. 第二层检查的意义:并发时,可能有多个线程躲过了第一层检查,在锁内部判断,确保仅有一个线程创建实例。

    注:只有实例未被创建之前的调用是单线程。

  • 非懒惰线程安全。

    public sealed class SingletonV4
    {
        private static readonly SingletonV4 instance = new SingletonV4(); // -> 1
    
        // Explicit static constructor to tell C# compiler
        // not to mark type as beforefieldinit
        static SingletonV4()
        {
        }
    
        private SingletonV4()
        {
        }
    
        public static SingletonV4 Instance
        {
            get
            {
                return instance;
            }
        }
    }
    

    解:单例会在首次触发静态属性/方法时,生成实例。

    注:若类中存在静态属性/方法时,调用静态属性/方法也会创建实例,导致单例提前工作。

  • 推荐完全懒惰线程安全。

    public sealed class SingletonV5
    {
        private SingletonV5()
        {
        }
    
        public static SingletonV5 Instance { get { return Nested.instance; } } // -> 1
    
        private class Nested
        {
            // Explicit static constructor to tell C# compiler
            // not to mark type as beforefieldinit
            static Nested()
            {
            }
    
            internal static readonly SingletonV5 instance = new SingletonV5(); 
        }
    }
    

    注:仅在首次使用【SingletonV5.Instance】时,会创建实例。

  • 懒加载线程安全。

    public sealed class SingletonV6
    {
        private static readonly Lazy<SingletonV6> lazy =
            new Lazy<SingletonV6>(() => new SingletonV6());
    
        public static SingletonV6 Instance { get { return lazy.Value; } }
    
        private SingletonV6()
        {
        }
    }
    

    注:使用懒加载,保证所有线程使用的实例相同,但并一定只会初始化一次实例。

    引用:

  • 强力推荐完全懒惰线程安全--反射。

    public class SingletonV7<T> where T : class
    {
        static SingletonV7() { }
    
        public static T Instance => Nested.Instance;
    
        private static class Nested
        {
            static Nested() { }
    
            public static readonly T Instance = (T)Activator.CreateInstance(typeof(T), true); // -> 1
        }
    }
    

    解:

    1. 作为基类。

      定义:继承SingletonV7<T>,其中T是需要作为单例的类。

      public sealed class Singleton : SingletonV7<Singleton>
      {
          private Singleton() { }
          
          public int Add(int i, int j) => i + j;
      }
      

      用法:

      int value = Singleton.Instance.Add(1, 2);
      
    2. 作为工具类。

      定义:任意包含(公共/私有)无参构造函数的类。

      public sealed class Singleton
      {
          private Singleton() { }
          
          public int Add(int i, int j) => i + j;
      }
      

      用法:

      int value = Singleton.Instance.Add(1, 2);
      
上一篇:【记】创建 VirtualBoxClient COM 对象失败. 应用程序将被中断


下一篇:创建DirectInput接口对象说明---(void **)&m_pDI