单例模式:就是在整个应用程序中只能有一个该类的实例,并提供一个访问它的全局访问点。
思路:每个类都有默认的无参数构造函数,若有显示定义的构造函数,默认的构造函数就失效,再把显示的构造函数写为private,外部就不能调用。
class Singleton { private static Singleton instance; private static readonly object syncRoot = new object(); private Singleton() { } public static Singleton GetInstance() { lock (syncRoot) { if (instance == null) { instance = new Singleton(); } } return instance; } }
这种代码每次GetInsstance()时,都要lock一下,防止其他线程进入,效率较低。
双重锁定
class Singleton { private static Singleton instance; private static readonly object syncRoot = new object(); private Singleton() { } public static Singleton GetInstance() { if (instance == null) { lock (syncRoot) { if (instance == null) { instance = new Singleton(); } } } return instance; } }
这种情况除了对象没有实例化之前进入的那批线程,以后的线程都直接返回已经生产的实例,不需要lock了。
这种不让线程每次都加锁,而只是在实例未被创建的时候再加锁处理,同时也保证了线程的安全,这种做法叫做Double-Check Locking(双重锁定);
两次判断是否为空
当instance存在时,直接返回。
当几个线程一起通过第一个判断是否为空时,其中一个lock,其他线程在外排队等候,等进去的出来以后,如果没有第二个判断,那就会创建多个实例。
静态初始化
C#与公共语言运行库也提供了静态初始化方法,这种方法不需要程序员编写线程安全代码
public sealed class Singleton { private static readonly Singleton instance = new Singleton();//CLR private Singleton() { } public static Singleton GetInstance() { return instance; } }
readonly:意味着只能在静态初始化期间或在类构造函数中分配变量
这种静态初始化方式是在自己被加载的时就将自己实例化,所有形象的被称为饿汉式单例类。会提前占用系统资源
上面的单例模式要在第一次被引用的时候才会将自己实例化,被称为懒汉式单例类。
public class Singletonwhere T:class{ private static Singleton instance; private static readonly object syncRoot = new object(); private Singleton() { }public static Singleton GetInstance() { if (instance == null) { lock (syncRoot) { if (instance == null) { instance = new Singleton (); } } } return instance; }}
我还以为这是 泛型 单例模式呢
public class Singletonwhere T:class{ private static T instance; private static readonly object syncRoot = new object(); private Singleton() { } public static T GetInstance() { if (instance == null) { lock (syncRoot) { if (instance == null) { instance = (T)Activator.CreateInstance(typeof(T), true); } } } return instance; }}
这个才是