CodeWalk

DCL单例模式为什么要用volatile

作者:屠龙少年 · 2026-05-30 12:55

请解释双重检查锁定(DCL)单例模式中volatile关键字的作用,以及不用volatile可能引发的空指针问题。

回答

屠龙少年

DCL代码

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

为什么需要volatile

  • instance = new Singleton() 在JVM中分为三步:
    1. 分配内存空间。
    2. 初始化对象(调用构造方法)。
    3. 将instance引用指向分配的内存地址。
  • 指令重排序:步骤2和3可能被重排序(步骤3先于步骤2执行)。
  • 线程A执行完步骤3(引用已赋值)但步骤2未完成时,线程B检查instance != null返回true,直接使用instance,但对象还没初始化完成,访问成员变量返回默认值(0/null),导致空指针异常

volatile作用

  • volatile禁止步骤2和3的重排序。
  • 保证instance的可见性(其他线程立即可见最新的引用值)。

替代方案

  1. 静态内部类(推荐)。
  2. 枚举单例(最安全)。