You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为什么Java线程安全Singleton单例代码运行失败?双检锁实现问题咨询

问题解答

你当前写的带synchronized块的代码本身无法正常运行,因为第一次调用getInstance()方法时instance还是null,synchronized(null)会直接抛出空指针异常,这也是你删掉同步块、取消下方if判断注释后程序才能运行的核心原因。


你修改后的版本(无同步块、仅保留单层if判断)确实不满足线程安全要求,具体问题如下:

  • 多线程并发调用getInstance()时,可能有多个线程同时判断instance == null为真,会各自创建Singleton实例,最终出现多个实例,完全违背单例模式的核心要求。
  • 没有同步机制的保护下,JVM的指令重排序可能会让其他线程拿到还未完成构造过程的半初始化Singleton对象,引发未知的运行错误。

符合作业要求的双重检查锁定正确实现如下:

class Singleton {
    // volatile禁止指令重排,保证多线程下的可见性
    volatile private static Singleton instance = null;
    private String someText;

    private Singleton() {
        this.someText = "Only one instance of this class can be created!";
    }

    public static Singleton getInstance() {
        // 第一层检查:已经初始化的情况下直接返回,避免每次都抢锁
        if (instance == null) {
            // 锁类对象而不是null的instance
            synchronized (Singleton.class) {
                // 第二层检查:抢到锁之后再判断一次,避免多线程同时过了第一层检查重复创建
                if (instance == null) {
                    instance = new Singleton();
                }
            }
        }
        return instance;
    }

    public String getSomeText() {
        return this.someText;
    }

    public void setSomeText(String text) {
        this.someText = text;
    }
}

public class Assignment1 {
    public static void main(String[] args) {
        Singleton singleton1 = Singleton.getInstance();
        Singleton singleton2 = Singleton.getInstance();
        System.out.println(singleton1.getSomeText());
        System.out.println(singleton2.getSomeText());
        singleton1.setSomeText("Here's our new text!");
        System.out.println(singleton1.getSomeText());
        System.out.println(singleton2.getSomeText());
    }
}

这种实现既保证了线程安全,又避免了每次调用getInstance()都需要加锁的性能损耗,完全符合双重检查锁定的设计要求。


内容的提问来源于stack exchange,提问作者Mint

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.29 23:09:03