单例模式:保证一个类仅有一个实例,并提供一个访问它的全局访问点。
构成:
1.私有的构造函数
2.私有静态的实例
3.返回实例的静态方法
public class Singleton { PRivate static Singleton uniqueInstance = new Singleton(); private Singleton() { Console.WriteLine("this is a new singleton"); } public static Singleton getInstance() { if (uniqueInstance == null) { return uniqueInstance; } return uniqueInstance; } }
这种叫做饿汉模式,实例在类加载时就创建了,缺点是如果实例如果消耗大量的资源而没有使用就会造成浪费,另一种懒汉模式,实例在被使用时才创建,
public class Singleton { private static Singleton uniqueInstance; private Singleton() { Console.WriteLine("this is a new singleton"); } public static Singleton getInstance() { if (uniqueInstance == null) { return uniqueInstance = new Singleton(); } return uniqueInstance; } }
但是这不是线程安全的
例如
class Program { static void Main(string[] args) { while (true) { Thread t1 = new Thread(Test); t1.Start(); } } static void Test() { Singleton s = Singleton.getInstance(); } }
执行的结果有可能是这样
程序创建了多个实例,这不是我们想要的结果,原因是某个线程if (uniqueInstance == null)语句执行后让出了使用权,当它重新获得CPU使用权的时候,可能别的CPU已经创建了实例,而它并不知道,继续执行return uniqueInstance= new Singleton();导致出现多个实例。
因此,要为方法加锁
public class Singleton { private static Singleton uniqueInstance; private Singleton() { Console.WriteLine("this is a new singleton"); } private static readonly object syncRoot = new object(); public static Singleton getInstance() { lock (syncRoot) { if (uniqueInstance == null) { return uniqueInstance = new Singleton(); } } return uniqueInstance; } }
但是这又带来了一个问题,在实例已经创建完成了,但还是会有大量的线程卡在lock (syncRoot),它们都还会尝试创建实例,这降低了性能
为此,还要为此方法创建另外一个验证
public static Singleton getInstance() { if (uniqueInstance == null) { lock (syncRoot) { if (uniqueInstance == null) { return uniqueInstance = new Singleton(); } } } return uniqueInstance; }
此时,当实例已经创建完成之后,各线程不再访问临界区,提高了性能
单例模式和静态类的比较
1.单例模式可以懒加载,静态类执行更快(为什么?),即在不同条件下二者有不同的性能表现
2.单例可以继承和override
3.单例易于模拟,利于测试
4.单例利于维护状态信息
新闻热点
疑难解答