1.什么是单例模式?
确保一个类只有一个实例,并提供一个全局访问点。
通俗易懂就是:每次去实例化一个对象都是同一个,指向的都是同一个内存地址。
2.为什么要使用单例模式,单例模式的好处在哪?
3.单例模式在C#中的具体实现。
/// <summary> /// 单例模式的简单实现 /// </summary> public class Singleton { /// <summary> /// 创建全局静态变量 /// </summary> private static Singleton _singleton = null; /// <summary> /// 私有化默认构造器,为什么要私有化默认构造器,如果不私有,那么可以通过new Singleton()进行实例化对象了,就达不到预想效果。 /// </summary> private Singleton() { } /// <summary> /// 提供一个创建实例的方法 /// </summary> /// <returns></returns> public static Singleton CreatInstance() { //判断,如果对象没有创建,那么进行创建。有创建,不在重复创建 if (_singleton == null) { _singleton=new Singleton(); } return _singleton; } }
测试结果如下:
//多线程模拟,十个线程同时访问 for (int i = 0; i < 10; i++) { new Action(() => { Thread.Sleep(1000); Singleton singleton = Singleton.CreatInstance(); singleton.Show(); //在Singleton类里面添加一个无参的Show方法 }).BeginInvoke(null, null); }

//判断,如果对象没有创建,那么进行创建。有创建,不在重复创建 if (_singleton == null) { _singleton=new Singleton(); }
会去判断这个对象是否已经被实例化,因为程序执行速度是很快的,当第一个线程发现对象未实例化时,第一个线程开始对对象进行实例化,第一个线程还未实例化完成第二个线程就已经进来了,开始对对象进行判断,开始实例化。最终造成如上效果。
public class Singleton { /// <summary> /// 创建全局静态变量 /// </summary> private static Singleton _singleton = null; private static object singleton_lock=new object(); /// <summary> /// 私有化默认构造器 /// </summary> private Singleton() { Console.WriteLine("创建了Singleton对象的实例"); } /// <summary> /// 提供一个创建实例的方法 /// </summary> /// <returns></returns> public static Singleton CreatInstance() { lock (singleton_lock) { //判断,如果对象没有创建,那么进行创建。有创建,不再重复创建 if (_singleton == null) { _singleton = new Singleton(); } } return _singleton; } public void Show() { Console.WriteLine($"执行Show方法:{this.GetType()}"); } }
运行后如下图:
多线程同时访问的情况下的问题就已经解决了。当然还可以再次优化一下,为了看到效果,对代码进行如下改造
改造之后再次执行
如上图发现,每一个线程都进入lock里面,如果第一个线程进入lock实例化了对象,那么第二个就可以没有必要进入lock,我们可以在线程进入lock前进行判断,最终代码改造如下,
/// <summary> /// 单例模式的简单实现 /// </summary> public class Singleton { /// <summary> /// 创建全局静态变量 /// </summary> private static Singleton _singleton = null; private static object singleton_lock=new object(); /// <summary> /// 私有化默认构造器 /// </summary> private Singleton() { Console.WriteLine("创建了Singleton对象的实例"); } /// <summary> /// 提供一个创建实例的方法 /// </summary> /// <returns></returns> public static Singleton CreatInstance() { if (_singleton == null) { lock (singleton_lock) { Console.WriteLine("开始进入lock..."); //判断,如果对象没有创建,那么进行创建。有创建,不在重复创建 if (_singleton == null) { _singleton = new Singleton(); } } } return _singleton; } public void Show() { Console.WriteLine($"执行Show方法:{this.GetType()}"); } }
执行效果如下
图中发现线程进入lock的次数少了,线程并发少可能作用不大,如果是并发量达到百万次甚至更多,那么效率会有明显提升。双if加lock是最标准的实现单例模式的写法。
接下来介绍两种比较简便的单例模式的实现,效果和上面的一样。
方式二、
public class SingletonSecond { private static SingletonSecond _singletonSecond = new SingletonSecond(); private SingletonSecond() { Console.WriteLine("创建了该对象的实例"); } public static SingletonSecond CreatInstance() { return _singletonSecond; } public void Show() { Console.WriteLine($"执行Show方法:{this.GetType()}"); } }
方式三、
public class SingletonThrird { private static SingletonThrird _singletonThrid = null; private SingletonThrird() { Console.WriteLine("创建了该对象的实例"); } static SingletonThrird() { _singletonThrid=new SingletonThrird(); } public static SingletonThrird CreatInstance() { return _singletonThrid; } public void Show() { Console.WriteLine($"执行Show方法:{this.GetType()}"); } }
以上就单例模式的实现方式。提供参考,职场小白欢迎指正!