单例模式

前言

  单例模式(Singleton),保证一个类仅有一个实例,并提供一个访问它的全局访问点。

一、简单模式

  

 1     public class Singleton1
 2     {
 3         private static Singleton1 instance;
 4         //构造私有,不能创建实例
 5         private Singleton1()
 6         {
 7 
 8         }
 9         //获得笨类实例的唯一全局访问点
10         public static Singleton1 GetInstance()
11         {
12             if (instance == null)
13             {
14                 instance = new Singleton1();
15             }
16             return instance;
17         }
18     }

二、多线程保护模式

  lock是确保当一个线程位于代码的临界区时,另一个线程不进入临界区。如果其他线程试图进入锁定的代码,则它将一直等待(即被阻止),知道该对象被释放。

 1     //多线程时的单例
 2     public class Singleton2
 3     {
 4         private static Singleton2 instance;
 5         //程序运行时创建一个静态只读的进程辅助对象
 6         private static readonly object syncRoot = new object();
 7         //构造私有,不能创建实例
 8         private Singleton2()
 9         {
10 
11         }
12         //获得笨类实例的唯一全局访问点
13         public static Singleton2 GetInstance()
14         {
15             //在同一时刻加了锁的那部分程序只有一个线程可以进入
16             lock (syncRoot)
17             {
18                 if (instance == null)
19                 {
20                     instance = new Singleton2();
21                 }
22             }
23             return instance;
24         }
25     }

  这样每次调用GetInstance方法时都需要lock,会影响性能,所以有了下面的双重锁。

三、双重锁

  当instance为null并且同时有两个线程调用GetInstance()方法时,他们讲都可以通过第一重instance == null的判断。然后由于lock机制,这两个线程则只有一个进入,另一个在lock那里排队等候,必须要其中的一个进入并出来后,另外一个才能进入。

  如果没有第二重instance == null的判断,则第一个线程创建了实例,而第二个线程还可以继续创建实例。

  

 1     public class Singleton3
 2     {
 3         private static Singleton3 instance;
 4         //程序运行时创建一个静态只读的进程辅助对象
 5         private static readonly object syncRoot = new object();
 6         //构造私有,不能创建实例
 7         private Singleton3()
 8         {
 9 
10         }
11         //获得笨类实例的唯一全局访问点
12         public static Singleton3 GetInstance()
13         {
14             //先判断实例是否存在,不存在再加锁处理
15             if (instance == null)
16             {
17                 //在同一时刻加了锁的那部分程序只有一个线程可以进入
18                 lock (syncRoot)
19                 {
20                     if (instance == null)
21                     {
22                         instance = new Singleton3();
23                     }
24                 }
25             }
26             return instance;
27         }
28     }

四、静态初始化

  C#与公共语言运行库提供了一种 ‘静态初始化’ 方法,这种方法不需要开发人员显式地编写线程安全代码,即可解决多线程环境下它是不安全的问题。

  

 1     //密封类不能被继承
 2     public sealed class Singleton4
 3     {
 4         //在第一次引用类的任何成员时创建实例。公共语言运行库负责处理变量初始化
 5         private static readonly Singleton4 instance = new Singleton4();
 6 
 7         private Singleton4() { }
 8         public static Singleton4 GetInstance()
 9         {
10             return instance;
11         }
12     }

  

  这种静态初始化的方式在自己被夹在时就将自己实例化,所以被形象地称为饿汉式单例类

  原来的单例 模式是要在第一次被引用时,才会将自己实例化,所以就被称为懒汉式单例类

总结

  参考数据:大话设计模式

原文地址:https://www.cnblogs.com/hyunbar/p/9964843.html