当前位置: 首页 > news >正文

设计模式 - 单例模式 - Tips

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

if (instance == null) {             synchronized (Singleton.class) {                                 if (instance == null) {                     instance = new Singleton();                 }             }         
}

instance = new Singleton();

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

  1. 为 Singleton 分配内存地址

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

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

假设线程 A 正在执行:

instance = new Singleton();   

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

  • 访问尚未初始化的字段

  • 抛出 NullPointerException

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

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

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 中只会被加载一次

相关文章:

  • [ctfshow web入门] web77
  • OpenCV 特征检测全面解析与实战应用
  • AI知识梳理——RAG、Agent、ReAct、LangChain、LangGraph、MCP、Function Calling、JSON-RPC
  • 【滑动窗口】LeetCode 209题解 | 长度最小的子数组
  • 系统架构设计(七):数据流图
  • 使用Docker部署Nacos
  • 【C++详解】string各种接口如何使用保姆级攻略
  • 区块链可投会议CCF C--IPCCC 2025 截止6.7 附录用率
  • 共享内存【Linux操作系统】
  • 【爬虫】DrissionPage-6
  • JavaScript【6】事件
  • 进阶-数据结构部分:​​​​​​​2、常用排序算法
  • 动态规划(3)学习方法论:构建思维模型
  • MATLAB2025新功能
  • 2025/517学习
  • STM32 | FreeRTOS 消息队列
  • Flink 数据传输机制
  • 6.1.1图的基本概念
  • DeepSeek快速指南:提升效率,告别内耗
  • 深入理解 requestIdleCallback:浏览器空闲时段的性能优化利器
  • 世界高血压日|专家:高血压患者控制血压同时应注重心率管理
  • 贞丰古城:新垣旧梦间的商脉与烟火
  • 土耳其、美国、乌克兰三边会议开始
  • 阿联酋与美国达成超过2000亿美元协议
  • 自然资源部:不动产登记累计化解遗留问题房屋2000多万套
  • 证监会:2024年依法从严查办证券期货违法案件739件,作出处罚决定592件、同比增10%