单例模式


单例模式,保证一个类仅有一个实例,并提供一个访问它的全局访问点。通常我们可以让一个全局变量使得一个对象被访问,但它不能防止你实例化多个对象。一个最好的办法就是让类自身负责保存它的唯一实例。这个类可以保证没有其他实例可以被创建,并且它可以提供一个访问该实例的方法。
单例模式:是一种常用的软件设计模式,通过单例模式可以保证系统中一个类只有一个实例而且该实例易于外界访问,从而方便对实例个数的控制并节约系统资源。

饿汉模式:这种模式下,无需自己解决线程安全性问题,CLR会给我们解决,当此类被加载时,会自动实例化这个类,
而不用在第一次调用GetInstance后才实例化出唯一的单例对象

public sealed class Singleton{ //sealed阻止发生派生类,而派生类可能会增加实例
private static readonly Singleton instance = new Singleton(); //readonly:在第一次引用类的任何成员时创建实例。公共语言运行库负责处理变量初始化
private Singleton(){

}
public static Singleton GetInstance(){
      return instance;
}
}


懒人模式:
内层if:先加锁,保证只有一个线程可以访问该语句块,进而保证了只创建一个实例
外层if:使每个线程获取实例时,不必每次都得加锁,只有实例为空时,才需加锁创建,若已存在一个实例,就直接返回该实例,节省了性能开销


public sealed class Singleton{

private static Singleton instance;
private static object _lock=new object();
private Singleton(){

}

public static Singleton GetInstance(){

if(instance==null){

lock(_lock){

if(instance==null){

instance = new Singleton();

}

}

return instance;

}

}

}

为啥lock里面还需要做一次instance实例是否存在的判断?
答:当instance为null并且同时又两个线程调用GetInstance方法时,它们将都可以通过第一重instance==null的判断。然后由于lock机制,这两个线程则只有一个进入,另一个在外排队等候,必须要其中的一个进入并出来后,另一个才能进入。而此时如果没有了第二重的instance是否为null的判断,则第一个线程创建了实例,而第二个线程还是可以继续再创建新的实例,这就没有达到单例的目的。

 

区别:
    饿汉模式的特点是加载类时比较慢,但运行时获取对象的速度比较快,线程安全。饿汉式是线程安全的,在类创建的同时就已经创建好一个静态的对象供系统使用,以后不在改变。
    懒汉模式的特点是加载类时比较快,但是在运行时获取对象的速度比较慢,线程不安全, 懒汉式如果在创建实例对象时不加上lock则会导致对象的访问不是线程安全的。
    所以在此推荐大家使用饿汉模式

原文地址:https://www.cnblogs.com/xiaoweigogo/p/7793723.html