news 2026/2/2 4:29:02

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/1/31 4:15:32

揭秘AI原生应用领域用户画像的模型可解释性问题

从黑盒到透明:AI原生应用中用户画像的可解释性实践 一、为什么要聊AI原生应用的用户画像可解释性? 你有没有遇到过这样的场景? 打开一款AI原生社交APP,首页推荐的内容全是你完全不感兴趣的话题,你盯着屏幕疑惑&#xf…

作者头像 李华
网站建设 2026/2/1 7:29:17

国内加速下载HunyuanOCR模型的方法汇总(含清华源)

国内加速下载HunyuanOCR模型的方法汇总(含清华源) 在企业智能化转型的浪潮中,文档自动化处理正成为效率提升的关键突破口。无论是银行票据识别、跨境商品信息提取,还是政务文件数字化,光学字符识别(OCR&am…

作者头像 李华
网站建设 2026/2/1 15:32:22

lora-scripts真实案例分享:方言语音识别模型微调过程详解

lora-scripts真实案例分享:方言语音识别模型微调过程详解 在智能语音助手几乎人手可用的今天,一个尴尬的问题依然存在:它们听不懂“家乡话”。无论是粤语里一句地道的“落雨收衫”,还是闽南语中“食未”的问候,通用语音…

作者头像 李华
网站建设 2026/1/30 11:38:30

negative prompt优化建议:提升lora-scripts训练后图像生成质量

negative prompt优化建议:提升lora-scripts训练后图像生成质量 在如今人人都能点几下鼠标就“训练出一个专属风格模型”的时代,LoRA 技术的普及让图像生成的门槛前所未有地降低。借助像 lora-scripts 这样的自动化训练工具,哪怕没有深厚深度学…

作者头像 李华
网站建设 2026/1/31 12:03:38

lora-scripts助力垂直领域大模型适配:医疗、法律、教育行业问答定制

LoRA-Scripts助力垂直领域大模型适配:医疗、法律、教育行业问答定制 在医院的智能导诊系统中,患者提问“孩子发烧38.5度该吃什么药?”如果AI回答“建议服用头孢克肟”,而未提示需医生确诊后再用药——这不仅误导用户,…

作者头像 李华
网站建设 2026/1/30 17:58:57

AI模型部署成本太高?试试仅1B参数的腾讯混元OCR解决方案

轻量化也能高性能?腾讯混元1B参数OCR如何破局AI部署成本困局 在智能文档处理日益普及的今天,企业对OCR技术的需求早已从“能识别文字”升级为“精准提取结构化信息”。然而现实却令人无奈:高精度OCR系统动辄需要多卡A100部署,推理…

作者头像 李华