单例模式
一、饿汉式->单例一开始就初始化好,只要有请求就给,此时的无论多少个请求都指向同一个单例。这里也可以将初始化操作 _instance = new BufferHandler() 放在构造函数中。
private static BufferHandler _instance = new BufferHandler(); public static BufferHandler GetOneIns() { return _instance; }
二、懒汉式->单例只有在请求的时候才初始化并返回给请求者,如果是多线程请求有可能请求到的两个是不同的单例,这样就会线程不安全。
如何理解懒汉式:即延迟加载,饿汉式在该类初始化时即初始化该单例,而懒汉式可以发现只有在请求此单例时才会被初始化,故称懒汉式(lazy_load);
private static BufferHandler _instance; public static BufferHandler GetOneIns() { if (_instance == null) _instance = new BufferHandler(); return _instance; }
三、内部静态类
懒汉式的延迟加载思想也可以应用于饿汉式中,此时需要借用一个内部静态类来实现。既实现了延迟创建,又保证了单例的线程安全。
private static BufferHandler _instance; private static class BufferInstanceInstanceCreater { public static readonly BufferHandler Instance = new BufferHandler(); } public static BufferHandler GetOneIns() { return BufferInstanceInstanceCreater.Instance; }
四、双重锁线程同步
public static object _inslock = new object(); private static BufferHandler _instance; public static BufferHandler GetOneIns() { if (_instance == null) { lock (_inslock) { if (_instance == null) _instance = new BufferHandler(); } } return _instance; }
为什么要用双重锁?
第一层 if (instance == null)是为了减少线程对同步锁锁的竞争,第二层if(instance==nul)是保证单例。
即第一层判断,如果单例已经存在的话就可以直接获得已经创建好的单例(即已经被缓存起来了),不需要进行同步锁lock操作,即减少竞争同步锁;第二步则是如果进程1同步锁时已经有另外一个进程2在占用同步锁,意味着进程2在申请单例。那么当同步锁释放时,进程1获得了同步锁资源,而此时单例也被创建好了,因此此时也需要一次判断。