双检锁方式实现的线程安全的单例模式中,第二个if有必要吗?
双检锁方式实现的线程安全的单例模式代码:
class Singleton{
private volatile static Singleton instance = null;
private Singleton() {
}
public static Singleton getInstance() {
if(instance==null) {
synchronized (Singleton.class) {
if(instance==null)
instance = new Singleton();
}
}
return instance;
}
}
分析一下上述代码:
- 最里面的if体现了懒汉这两个字:需要时再创建
- synchronized 的作用是防止并发时instance 多次实例化
- 最外层的if是防止synchronized拖慢执行效率
问题来了
两个if同时写,第二个if还有必要吗?
当然有!
两个if都是必须的。如果刚开始有两个线程同时调这个方法,这个两个线程同时进入第一个if,但是只有一个进入到了synchronized里面,然后初始化instance,再退出来。然后第二个线程再进入synchronized里面,此时instance已经初始化了,如果没有第二个if,instance就会再次初始化,导致创建多个实例。
简单来说就是第一个if判断过instance==null之后,instance可能还会变化。