JAVA面试-并发篇 03-使用synchronized doublecheck实现单例有什么坑

DCL(Double-Check Locking 双重检查锁)单例的坑

一、核心结论

经典DCL最致命的是volatile缺失导致的半初始化对象空指针

二、错误 vs 正确完整写法

❌ 错误写法(90%的人会写错,缺volatile)

java 复制代码
public class Singleton {
    // 致命错误:缺少volatile关键字
    private static Singleton instance;
    
    // 私有构造方法
    private Singleton() {}
    
    public static Singleton getInstance() {
        // 第一次检查(无锁)
        if (instance == null) {
            // 加锁
            synchronized (Singleton.class) {
                // 第二次检查(有锁)
                if (instance == null) {
                    instance = new Singleton();
                }
            }
        }
        return instance;
    }
}

✅ 正确写法(加volatile禁止指令重排序)

java 复制代码
public class Singleton {
    // 关键:加上volatile关键字
    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;
    }
}

三、最致命坑:指令重排序

对象创建的两种执行顺序

复制代码
┌───────────── 正常顺序(安全) ─────────────┐
│ 1. 分配对象内存空间                        │
│ 2. 初始化对象(执行构造方法)              │
│ 3. 将instance引用指向该内存地址            │
└───────────────────────────────────────────┘

┌───────────── 重排序后(危险) ─────────────┐
│ 1. 分配对象内存空间                        │
│ 3. 将instance引用指向该内存地址            │
│ 2. 初始化对象(执行构造方法)              │
└───────────────────────────────────────────┘

灾难发生完整流程

复制代码
线程A执行 instance = new Singleton()
        ↓
JVM发生指令重排序:先执行步骤3,后执行步骤2
        ↓
instance ≠ null,但对象内部数据全是默认值(未初始化)
        ↓
线程B执行第一次检查:发现instance≠null,直接返回
        ↓
线程B使用这个"半成品"对象 → 抛出NullPointerException
相关推荐
二炮手亮子5 分钟前
java责任链模式
java
AI深栈21 分钟前
第 10 章 · Embedding、VectorStore 与 RAG
java·人工智能
ocean210343 分钟前
2025-2026年C++专题大厂面试高频问题
开发语言·c++·面试
Java内核笔记43 分钟前
Spring Boot 4 SSRF 防护源码剖析:InetAddressFilter 挡住内网地址与云元数据
java·后端
顶点多余1 小时前
9.15 面试问题总结(一面挂)
linux·面试·职场和发展
白远山1 小时前
健身场馆无人自动化系统实战指南:从架构设计到部署全流程解析
java·开发语言·架构·需求分析
user_admin_god1 小时前
第 09 篇:实践一 —— 文本摘要(Map-Reduce 分块)
java·人工智能·spring boot·语言模型
咖啡八杯1 小时前
Controller 基类封装:BaseController 的模板方法设计
java·架构·设计
vx_BS813301 小时前
【项目编号:project49759】Spring Boot 宠物综合服务平台:商城、预约、咨询、活动与健康档案的一体化实现
java·spring boot·eclipse·tomcat·intellij-idea
她的男孩1 小时前
加了 @Idempotent 还是重复扣款了 3 笔:扒完 1279 行幂等 Starter,我挖出 5 个隐蔽的坑
java·后端·架构