设计模式 - 单例模式 - Tips

为什么双重检查会带来空指针异常 问题?

java 复制代码
if (instance == null) {             
    synchronized (Singleton.class) {                                 
        if (instance == null) {                     
            instance = new Singleton();                 
        }             
    }         
}

instance = new Singleton();

上述加粗的代码并不是原子操作,包含三个步骤:

  1. 为 Singleton 分配内存地址

  2. 执行 Singleton() 构造方法,初始化成员变量等

  3. 将内存地址赋值给 instance 变量

假设线程 A 正在执行:

java 复制代码
instance = new Singleton();   

由于指令 **重排序,**线程 A 可能在构造函数执行之前,就已经将内存地址赋值给 instance,导致 instance 变为非 null。此时线程 B 会认为 instance 已经是合法对象,于是直接使用,结果可能:

  • 访问尚未初始化的字段

  • 抛出 NullPointerException

  • 出现逻辑错误或不可预知的行为

为什么可以通过 静态内部类 实现懒汉式 单例模式 ?

java 复制代码
public class Singleton {     
    private Singleton() {}     
    
    private static class SingletonHolder {         
        private static final Singleton INSTANCE = new Singleton();     
    }        
    
    public static Singleton getInstance() {              
        return SingletonHolder.INSTANCE; 
    }  
}

这依赖于 Java 类加载机制的特性:

  • JVM 在加载外部类的过程中不会加载静态内部类,只有内部类的属性 / 方法被调用时才会进行加载(懒汉式)

  • JVM 在加载类的时候会自动保证线程安全,一个类在 JVM 中只会被加载一次

相关推荐
2301_780789666 小时前
跨平台适配!SDK 游戏盾兼容全终端游戏场景
java·网络·ddos
学长毕设7 小时前
基于springboot的食品仓库管理系统
java·spring boot·后端
步行cgn7 小时前
FormHttpMessageConverter 详解:Spring MVC 中表单数据的读写转换器
java·spring·mvc
龙亘川8 小时前
构建城市公共安全数字底座:亘川智城智慧安防系统全维度解读
java·大数据·开发语言·人工智能·信息可视化
金銀銅鐵8 小时前
[Java] 用 CLI 展示 EnumMap 增删键值对时的内部变化
java·源码·ai编程
秋天的怀念_David8 小时前
第二十二夜 · 数字迷雾
java·程序人生·算法
Raas1008 小时前
AI网关部署方案?从部署到上线全流程
java·开发语言·人工智能·gateway·ai网关·企业级ai网关·企业级ai产品
niucloud-admin9 小时前
NIUCLOUD PHP SAAS上门家政使用文档:城市管理
java·前端·php
霸道流氓气质9 小时前
智能客服组件:分层意图识别、RAG Advisor 与人工转接状态机的 Vue3 + Spring AI 生产级实战
java·人工智能·spring
captain37610 小时前
MyBatis操作数据库(入门2)
java·数据库·spring boot·后端·spring·mybatis