单例模式:进程唯一。
-
非线程安全。
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)个线程同时访问单例。
解:
- 实例并未创建,所有线程都能进入创建实例代码块。
- 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; } } }
解:
- 第一层检查的意义:当实例被创建后,不再进入锁。
- 第二层检查的意义:并发时,可能有多个线程躲过了第一层检查,在锁内部判断,确保仅有一个线程创建实例。
注:只有实例未被创建之前的调用是单线程。
-
非懒惰线程安全。
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 } }
解:
-
作为基类。
定义:继承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);
-
作为工具类。
定义:任意包含(公共/私有)无参构造函数的类。
public sealed class Singleton { private Singleton() { } public int Add(int i, int j) => i + j; }
用法:
int value = Singleton.Instance.Add(1, 2);
-