为什么在Java中设计单例模式时需要双重检查锁?

Jav*_*ser 1 java singleton synchronization design-patterns

为什么我们需要在锁定之前和之后检查null?有一次,我们获得了锁,没有线程可以拥有锁,那为什么在同步块之前不需要空检查?

public class DclSingleton {
    private static volatile DclSingleton instance;
    public static DclSingleton getInstance() {
        **if (instance == null) {**
            synchronized (DclSingleton .class) {
                **if (instance == null) {**
                    instance = new DclSingleton();
                }
            }
        }
        return instance;
    }

    // private constructor and other methods...
}
Run Code Online (Sandbox Code Playgroud)

tal*_*lex 5

想象一下下一个场景:

  1. 线程1检查instance == null并发现此条件为真.
  2. 线程2检查instance == null并发现此条件为真.
  3. 线程1获得锁定.
  4. 线程2尝试获取锁定,它已被获取,因此线程2等待.
  5. 线程1初始化instance = new DclSingleton().
  6. 线程1释放锁定.
  7. 线程2获得锁定.
  8. 线程2初始化instance = new DclSingleton().我们有双重初始化.