news 2026/6/23 7:53:41

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/6/13 17:36:40

基于YOLOv11的焊缝缺陷智能检测系统:从算法到UI界面的全流程落地

文章目录 【工业检测毕设利器】基于YOLOv11的焊缝缺陷智能检测系统:从算法到UI界面的全流程落地 一、项目价值:为什么做焊缝缺陷检测? 二、技术基石:YOLOv11到底强在哪? 三、数据集:从“找数据”到“喂饱模型” 1. 数据集去哪找? 2. 数据集怎么处理? 四、模型训练:让Y…

作者头像 李华
网站建设 2026/6/15 17:59:26

病理切片分析新征程:利用YOLOv11实现自动化检测与UI界面集成

文章目录 病理切片分析新征程:利用YOLOv11实现自动化检测与UI界面集成 引言 一、YOLOv11概述 1.1 YOLOv11简介 1.2 YOLOv11在病理切片分析中的应用 二、数据集准备与处理 2.1 数据集选择 2.2 数据预处理与增强 2.3 数据集划分 三、YOLOv11模型训练与优化 3.1 环境搭建 3.2 配置…

作者头像 李华
网站建设 2026/6/21 21:24:16

车间智能监控:基于YOLOv11_8_10的人员与设备状态实时监测系统解析

文章目录 车间智能监控:基于YOLOv11_8_10的人员与设备状态实时监测系统解析 一、引言 二、项目目标与意义 三、技术选型与工具准备 1. 模型选择 2. 工具准备 四、数据准备与训练 1. 数据采集 2. 数据标注 3. 数据增强 4. 数据集划分 五、模型训练与调优 1. YOLOv11训练 2. YOL…

作者头像 李华
网站建设 2026/6/22 18:24:32

厨房工具识别系统:基于YOLOv11的从入门到实战全流程指南

文章目录 厨房工具识别系统:基于YOLOv11的从入门到实战全流程指南 引读:让厨房工具识别准确率突破92%的实用方案 一、项目基石:厨房工具识别的需求与技术选型 二、环境搭建:从依赖安装到代码准备 1. 必备依赖安装 2. YOLOv11代码仓库获取 三、数据准备:让模型“看懂”厨房…

作者头像 李华
网站建设 2026/6/15 14:28:27

野生动物智能入侵检测:基于YOLOv11的生态安全监测方案

文章目录 野生动物智能入侵检测:基于YOLOv11的生态安全监测方案 一、项目背景:为什么要做动物入侵智能检测? 二、系统架构:从监测到预警的全流程设计 三、数据准备:让模型“认识”野生动物 (1)数据集选择 (2)数据标注与格式 (3)数据集组织与配置 四、YOLOv11模型训练…

作者头像 李华
网站建设 2026/6/21 6:18:34

用腾讯混元OCR做视频字幕提取,准确率高达SOTA水平

用腾讯混元OCR做视频字幕提取,准确率高达SOTA水平 在短视频日活突破十亿、在线教育课程年增百万的今天,如何从海量视频中高效获取结构化文本信息,已经成为内容平台、媒体机构乃至个人创作者面临的核心挑战。尤其是字幕提取这一任务——看似简…

作者头像 李华