我们常用的单例模式一般是两种 1.懒汉式单例 2.饿汉式单例。那么他们的性能如何,线程安全又如何呢?
1.懒汉模式
private static Singleton mInstance; public static Singleton getInstance() { if (mInstance == null) {//一重判空 synchronized (Singleton.class) { if (mInstance == null) {//二重判空 mInstance = new Singleton(); } } } return mInstance ; }
双重判空的意义在于,mInstance是静态变量,是线程不安全的。那么我们通过同步锁synchronized来锁定改类。如果不加第一个判空,那么每次调用getInstance()都会调一下同步锁,那么开销是很大的。如果加了第一个判空,那么大概率是只会调用一次同步锁。
所以双重锁是用来降低同步锁的调用次数的,是提升代码执行效率的。
2.饿汉式单例
除了双重锁,其实更好的是饿汉模式单例。
public class Singleton {
private static final Singleton mInstance = new Singleton();
}
直接在类加载的时候就调用实例化,如果构造函数里面没有开销太大的操作,并且执行构造函数时this没有被传给外部其他线程引用,那么饿汉模式就是非常好的。
首先,final类变量型基本上是线程安全的(构造函数this没有被传给外部其他线程引用),所以不需要同步锁,也不需要麻烦的判空,所以性能是很高的。