news 2026/9/3 2:56:56

Java 使用 volatile + 双重检查锁(DCL)实现单例模式的最佳方案

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Java 使用 volatile + 双重检查锁(DCL)实现单例模式的最佳方案

为什么要这么做?因为在并发场景下,双重检查锁(DCL)确实存在严重问题——

问题的核心根源

指令重排序

helper=newHelper();// 这不是原子操作

实际上包含三个步骤:

  1. Helper对象分配内存空间
  2. 调用构造函数初始化对象
  3. 将引用赋值给helper变量

问题在于:步骤2和步骤3可能被JVM重排序,导致另一个线程看到一个未完全初始化的对象

具体场景分析

// 线程1执行helper=newHelper();// 重排序后:分配内存 → 赋值引用 → 初始化// 在线程1赋值引用后、初始化前,线程2进入if(helper==null){// helper不为null,但对象未初始化!// 跳过同步块returnhelper;// 返回一个半成品对象!}

JDK5+的推荐解决方案

使用volatile关键字

classSingleton{privatevolatileHelperhelper=null;// 关键:添加 volatilepublicHelpergetHelper(){if(helper==null){// 第一次检查(无锁)synchronized(this){// 加锁if(helper==null){// 第二次检查(有锁)helper=newHelper();// 安全初始化}}}returnhelper;}}

volatile如何解决问题

1.禁止指令重排序

  • volatile写之前的所有操作,都不会被重排序到写之后
  • volatile读之后的所有操作,都不会被重排序到读之前
  • 具体来说:helper = new Helper()的初始化操作(构造函数调用)会在赋值之前完成

2.保证内存可见性

  • 当一个线程修改volatile变量时,新值会立即被刷新到主内存
  • 其他线程读取volatile变量时,会从主内存重新加载最新值

3.建立 happens-before 关系

根据JSR-133(Java内存模型增强)

  • volatile变量的写操作 happens-before 于后续对该变量的读操作
  • 这保证了所有线程看到的初始化状态是一致的

完整的线程安全示例

publicclassSafeDoubleCheckedLocking{// 必须使用 volatile 修饰privatevolatileResourceresource;publicResourcegetResource(){// 第一次检查:大多数情况不需要同步,提升性能Resourceresult=resource;if(result==null){// 同步块:确保只有一个线程初始化synchronized(this){result=resource;if(result==null){// volatile 保证初始化完成前不会发布引用resource=result=newResource();}}}returnresult;}staticclassResource{// 资源类的定义publicResource(){// 复杂的初始化逻辑}}}

为什么这个方案适用于JDK5+

Java内存模型的演进

  • JDK 1.4及之前:DCL根本无法正确实现,volatile语义不完整
  • JDK 5(JSR-133):重新定义了内存模型,强化了volatile的语义
    • 禁止特定类型的指令重排序
    • 建立了更强的 happens-before 关系
    • 修复了DCL的根本问题

替代方案比较

方案优点缺点
volatile + DCL性能好(大多数情况无锁)代码稍复杂,需要JDK5+
静态内部类简洁安全,延迟加载无法传参初始化
枚举单例绝对安全,防止反射攻击不够灵活
synchronized方法简单安全每次访问都同步,性能差

最佳实践建议

  1. 优先考虑其他单例模式

    • 静态内部类(如果不需要传参)
    • 枚举单例(如果需要绝对安全)
  2. 必须使用DCL时

    // 确保:// 1. 使用 volatile// 2. 使用JDK5+// 3. 两次检查都不省略
  3. 性能考量

    • DCL在初始化后几乎没有性能损耗
    • 适合初始化成本高、频繁访问的场景
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/2 23:11:11

lora-scripts版本更新日志跟踪:保持工具处于最新状态

lora-scripts版本更新日志跟踪:保持工具处于最新状态 在生成式人工智能(AIGC)技术飞速演进的今天,越来越多开发者和企业开始尝试通过微调大模型来满足特定场景需求。然而,全参数微调动辄需要数百GB显存与高昂算力成本&…

作者头像 李华
网站建设 2026/9/2 6:35:17

揭秘C++26 constexpr新特性:如何实现零成本抽象与极致性能优化

第一章:C26 constexpr编译优化概述C26 正在推进一系列针对 constexpr 的增强功能,旨在进一步扩展编译期计算的能力边界。这些改进不仅允许更多类型的代码在常量表达式中执行,还显著提升了模板元编程和泛型库的性能与可读性。编译期计算能力的…

作者头像 李华
网站建设 2026/9/3 2:31:46

lora-scripts与其他LoRA训练脚本的功能对比表

LoRA训练工具的进化:从脚本拼接到工程化实践 在生成式AI席卷各行各业的今天,一个现实问题摆在许多开发者和创意工作者面前:如何用有限的资源,让大模型学会“说我们的话”?无论是设计师想让Stable Diffusion理解自己的艺…

作者头像 李华
网站建设 2026/8/24 13:08:19

微PE官网安全提醒:避免误下病毒软件影响lora-scripts开发环境

微PE官网安全提醒:避免误下病毒软件影响LoRA开发环境 在AI模型微调日益平民化的今天,越来越多个人开发者借助LoRA技术定制专属的图像或语言模型。工具链的简化让“训练一个风格化AI”变得像安装普通软件一样简单——只需几条命令、一份配置文件&#xff…

作者头像 李华