双检锁方式实现的线程安全的单例模式中,第二个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;
    }
}

分析一下上述代码:

  1. 最里面的if体现了懒汉这两个字:需要时再创建
  2. synchronized 的作用是防止并发时instance 多次实例化
  3. 最外层的if是防止synchronized拖慢执行效率

问题来了

两个if同时写,第二个if还有必要吗?

当然有!

两个if都是必须的。如果刚开始有两个线程同时调这个方法,这个两个线程同时进入第一个if,但是只有一个进入到了synchronized里面,然后初始化instance,再退出来。然后第二个线程再进入synchronized里面,此时instance已经初始化了,如果没有第二个if,instance就会再次初始化,导致创建多个实例。

简单来说就是第一个if判断过instance==null之后,instance可能还会变化。