单例模式
单线程中可以这样使用
单例模式:顾名思义,就是在程序中某类只允许有一个实例。这样我们只需要在该类的内部做点手脚即可。
1 public class SingleTon 2 { 3 //创建私有的静态字段 4 private static SingleTon singeTon; 5 6 //私有构造函数 这样外面就不能通过new的方式创建该类的实例了 7 private SingleTon() 8 { 9 } 10 //在单线程中可以这样使用 静态的方法返回实例 11 public static SingleTon CreateSingleTon() 12 { 13 if (singeTon==null) 14 { 15 singeTon=new SingleTon(); 16 } 17 return singeTon; 18 } 19 }
上述代码在单线程中没有问题。但是在多线程中就会创建多个实例。这样我们需要给类的内部加上标志位,然后上锁。
多线程中的单例模式
同上面的模式差不多,只是多了一个用于上锁的对象
/// <summary> /// 多线程下创建单例 /// </summary> public class ThreadSingleTon { //同样使用静态的该类字段 private static ThreadSingleTon threadSingleTon; //创建一个静态只读的标志位,用于上锁 private static readonly object o=new object(); //为了外界不能直接new,同样使用私有构造函数 private ThreadSingleTon() { } /// <summary> /// 学名:该类访问统一入口,实际就是一个该类的静态方法,返回该类的实例 /// </summary> /// <returns></returns> private static ThreadSingleTon createThreadSingleTon() { //当第一个线程访问的时候,会对o对象上锁。 //当第二个线程访问的时候,会对o对象检查 状态,如果上锁,该线程会挂起,等待第一个线程解锁 //当lock语句运行完之后(线程运行完之后),会对o对象解锁。 lock (o) { if (threadSingleTon==null) { threadSingleTon=new ThreadSingleTon(); } } return threadSingleTon; } }
上面这种解决方案确实可以解决多线程的问题,但是上面代码对于每个线程都会对线程辅助对象locker加锁之后再判断实例是否存在,对于这个操作完全没有必要的,因为当第一个线程创建了该类的实例之后,后面的线程此时只需要直接判断(uniqueInstance==null)为假,此时完全没必要对线程辅助对象加锁之后再去判断,所以上面的实现方式增加了额外的开销,损失了性能,为了改进上面实现方式的缺陷,我们只需要在lock语句前面加一句(uniqueInstance==null)的判断就可以避免锁所增加的额外开销,这种实现方式我们就叫它 “双重锁定”。
双重锁定单例模式
public class DoubleCheckSingleTon { //同样使用静态的该类字段 private static DoubleCheckSingleTon doubleCheckSingleTon; //创建一个静态只读的标志位,用于上锁 private static readonly object o=new object(); //为了外界不能直接new,同样使用私有构造函数 private DoubleCheckSingleTon() { } /// <summary> /// 学名:该类访问统一入口,实际就是一个该类的静态方法,返回该类的实例 /// </summary> /// <returns></returns> private static DoubleCheckSingleTon CreateDoubleCheckSingleTon() { //当第一个线程访问的时候,会对o对象上锁。 //当第二个线程访问的时候,会对o对象检查 状态,如果上锁,该线程会挂起,等待第一个线程解锁 //当lock语句运行完之后(线程运行完之后),会对o对象解锁。 //只需要在检查一遍,就是双重锁定 if (doubleCheckSingleTon==null) { lock (o) { if (doubleCheckSingleTon == null) { doubleCheckSingleTon = new DoubleCheckSingleTon(); } } } return doubleCheckSingleTon; } }