【Java踩坑笔记】23_double-checkedlocking单例,你写的真的线程安全吗?
23 | double-checked locking 单例你写的真的线程安全吗摘要双重检查锁DCL是实现懒加载单例的经典写法但少了volatile就会返回半初始化的对象。本文从指令重排角度彻底讲清这个问题并给出更好的单例实现方案。一、问题现象// ❌ 不完整的 DCL 单例少了 volatilepublicclassSingleton{privatestaticSingletoninstance;// ❌ 少了 volatileprivateSingleton(){}publicstaticSingletongetInstance(){if(instancenull){// 第一次检查synchronized(Singleton.class){// 加锁if(instancenull){// 第二次检查instancenewSingleton();// ❌ 可能返回半初始化的对象}}}returninstance;}}问题instance new Singleton()不是原子操作可能发生指令重排另一个线程拿到的是半初始化的对象。二、踩坑现场场景高并发下单例对象字段为 nullpublicclassConfigManager{privatestaticConfigManagerinstance;// ❌ 没加 volatileprivatefinalMapString,Stringconfig;privateConfigManager(){configloadConfigFromDb();// 耗时操作}publicstaticConfigManagergetInstance(){if(instancenull){synchronized(ConfigManager.class){if(instancenull){instancenewConfigManager();}}}returninstance;}publicStringgetConfig(Stringkey){returnconfig.get(key);// ❌ 可能 NPEconfig 还没初始化完}}现象偶尔出现NullPointerException但无法稳定复现是生产环境最隐蔽的 bug 之一。三、原理解析3.1new Singleton()的底层步骤指令 1分配内存空间给 instance 指向这块内存 指令 2初始化对象调用构造方法给字段赋值 指令 3将 instance 指向分配的内存地址问题步骤 2 和步骤 3 可能被重排指令重排是 CPU 和编译器为了优化性能做的单线程下不影响结果。重排后指令 1分配内存空间 指令 3将 instance 指向分配的内存地址 ← 此时 instance ! null但对象还没初始化完 指令 2初始化对象3.2 另一个线程看到的情况线程 A执行 new Singleton() → 执行到指令 3instance 已非零但对象未初始化完 → 被挂起 线程 B调用 getInstance() → 第一次检查instance null→ falseinstance 已非零 → 直接 return instance但对象还没初始化完 → 使用这个半初始化的对象 → 出错3.3volatile如何修复volatile禁止指令重排privatestaticvolatileSingletoninstance;// ✅ 加 volatilepublicstaticSingletongetInstance(){if(instancenull){synchronized(Singleton.class){if(instancenull){instancenewSingleton();// ✅ volatile 禁止指令重排}}}returninstance;}volatile的 happens-before 规则对volatile变量的写操作happens-before后续对该变量的读操作换句话说instance的写步骤 3不会被重排到对象初始化步骤 2之前四、正确写法4.1 标准 DCL 单例Java 5// ✅ 正确加 volatilepublicclassSingleton{privatestaticvolatileSingletoninstance;// ✅ 必须加 volatileprivateSingleton(){}publicstaticSingletongetInstance(){if(instancenull){// 第一次检查无锁性能高synchronized(Singleton.class){if(instancenull){// 第二次检查防止多个线程同时通过第一次检查instancenewSingleton();}}}returninstance;}}4.2 枚举单例最推荐Effective Java 推荐// ✅ 最推荐枚举单例天然防止反射攻击、序列化问题publicenumSingleton{INSTANCE;// 枚举实例天然是单例publicvoiddoSomething(){// 业务逻辑}}// 使用Singleton.INSTANCE.doSomething();枚举单例的优势写法极简天然线程安全枚举实例的创建由 JVM 保证天然防止反射攻击枚举不能通过反射创建实例天然支持序列化不需要实现Serializable接口4.3 静态内部类单例推荐// ✅ 推荐静态内部类懒加载 线程安全publicclassSingleton{privateSingleton(){}privatestaticclassHolder{privatestaticfinalSingletonINSTANCEnewSingleton();}publicstaticSingletongetInstance(){returnHolder.INSTANCE;// ✅ 第一次调用时才加载 Holder 类懒加载}}原理类加载是线程安全的JVM 保证Holder类只被加载一次。4.4 简单场景直接用静态字段// ✅ 如果不需懒加载最简单publicclassSingleton{publicstaticfinalSingletonINSTANCEnewSingleton();privateSingleton(){}}五、最佳实践✅ 单例实现的方案选择方案推荐度懒加载线程安全防止反射/序列化攻击枚举单例⭐⭐⭐⭐⭐✅✅✅静态内部类⭐⭐⭐⭐✅✅❌需额外处理DCL volatile⭐⭐⭐✅✅❌需额外处理静态字段⭐⭐❌类加载时就初始化✅❌ 为什么 DCL 在 Java 1.4 及之前是坏的Java 1.5 之前volatile的语义不够强即使加了volatileDCL 依然可能返回半初始化的对象。Java 1.5 增强了volatile的语义JSR-133DCL 才变得安全。️ 阿里巴巴 Java 开发手册规约【推荐】枚举类名带上 Enum 后缀枚举成员名称需要全大写单词间用下划线隔开。【推荐】如若使用单例模式推荐使用枚举方式实现。六、小结DCL 单例少了volatile会返回半初始化的对象指令重排导致volatile禁止指令重排是 DCL 正确的关键最推荐用枚举单例Effective Java 推荐写法简单且天然安全其次是静态内部类单例懒加载 线程安全如果不需要懒加载直接用静态字段最简单下一篇预告CompletableFuture 的默认线程池生产环境慎用—— 共用ForkJoinPool.commonPool()IO 任务会拖垮整个 JVM 的异步任务。

相关新闻

IS31FL3731与MKV42F64VLH16的LED驱动与动画实现

IS31FL3731与MKV42F64VLH16的LED驱动与动画实现

1. IS31FL3731与MKV42F64VLH16的硬件协同架构在LED视觉项目中,IS31FL3731作为LED驱动芯片与MKV42F64VLH16微控制器的组合,实际上构建了一个典型的"控制器-驱动器"二级硬件体系。IS31FL3731是一款支持I2C接口的矩阵LED驱动器,能独立…

2026/7/3 14:55:52阅读更多 →
告别海外账号烦恼:Claude Code安装配置全流程(Linux/WSL2 版本)

告别海外账号烦恼:Claude Code安装配置全流程(Linux/WSL2 版本)

前言 这篇文章整理了 Claude Code 在Linux/WSL2 版本下的从0到1的保姆级教程,用 API 解决直连问题,搭配CC Switch管理模型,亲测在Linux/WSL2环境下能跑通。如果你也想少踩坑快速上手,跟着步骤做就行。 正文 1. 安装Node.js Cl…

2026/7/3 14:55:52阅读更多 →
BiSheng JDK 11深度解析:华为开源高性能Java运行时的终极指南

BiSheng JDK 11深度解析:华为开源高性能Java运行时的终极指南

BiSheng JDK 11深度解析:华为开源高性能Java运行时的终极指南 【免费下载链接】bishengjdk-11 BiSheng JDK 11 is a high-performance, production-ready distribution of OpenJDK 11. 项目地址: https://gitcode.com/openeuler/bishengjdk-11 前往项目官网免…

2026/7/3 14:50:51阅读更多 →
深入解析fastjson反序列化漏洞:从调用链原理到实战防御

深入解析fastjson反序列化漏洞:从调用链原理到实战防御

1. 项目概述:为什么我们要深挖fastjson的调用链?如果你是一名Java开发者,或者从事应用安全、渗透测试工作,那么“fastjson反序列化漏洞”这个词对你来说一定不陌生。它几乎成了Java生态里一个“经久不衰”的话题,每隔一…

2026/7/3 16:36:09阅读更多 →
IMU与MCU硬件协同设计实现6DoF数据采集

IMU与MCU硬件协同设计实现6DoF数据采集

1. 从3D到6DoF:IMU与微控制器的硬件协同设计在运动追踪和空间定位领域,6自由度(6DoF)数据采集一直是个既基础又关键的挑战。最近我在一个无人机飞控项目中,尝试用TDK的IIM-42652惯性测量单元(IMU)搭配Microchip的PIC18…

2026/7/3 16:36:09阅读更多 →
如何用ComfyUI-WanVideoWrapper将你的创意变成惊艳视频

如何用ComfyUI-WanVideoWrapper将你的创意变成惊艳视频

如何用ComfyUI-WanVideoWrapper将你的创意变成惊艳视频 【免费下载链接】ComfyUI-WanVideoWrapper 项目地址: https://gitcode.com/GitHub_Trending/co/ComfyUI-WanVideoWrapper 你是否曾经想过,只需几句话的描述,就能让AI帮你创作出专业级的视频…

2026/7/3 16:36:09阅读更多 →
6DoF运动跟踪技术:从IMU到姿态解算全解析

6DoF运动跟踪技术:从IMU到姿态解算全解析

1. 从3D到6DoF:运动跟踪的技术演进在运动感知和空间定位领域,3D跟踪已经不能满足现代应用的需求。6DoF(六自由度)跟踪技术正在成为工业自动化、VR/AR设备和无人机控制等场景的新标准。最近我在一个机器人定位项目中,尝…

2026/7/3 16:36:09阅读更多 →
AI大跃进:当狂热取代理性,我们正在重蹈覆辙?

AI大跃进:当狂热取代理性,我们正在重蹈覆辙?

[阅读原文]https://mp.weixin.qq.com/s/xJbN_S6oX8TIysjlrfKP4g?scene2&click_id1572112476 一、全民AI的狂欢盛宴 打开任何一个科技媒体、行业论坛或企业内部会议,你几乎都能听到同一个声音——“All in AI”。 从自媒体到创业公司,从传统企业到…

2026/7/3 16:36:09阅读更多 →
devkit-pipeline自动化测试框架:DevKitTester的10个高级技巧

devkit-pipeline自动化测试框架:DevKitTester的10个高级技巧

devkit-pipeline自动化测试框架:DevKitTester的10个高级技巧 【免费下载链接】devkit-pipeline Pipeline solution to support building, deploying and automating any software project on Kunpeng Architecture 项目地址: https://gitcode.com/openeuler/devki…

2026/7/3 16:31:08阅读更多 →
AI Coding 六个月真实ROI账本:产品经理的血泪教训,研发的冷静忠告

AI Coding 六个月真实ROI账本:产品经理的血泪教训,研发的冷静忠告

6个月前的2025年12月,Boris Cherny 公开宣布自己卸载了 IDE。一时间,Vibe Coding 成了全行业最热的话题。6个月后,当我们回过头来拉一份真实账本,发现事情远没有"一句话生成一个App"那么浪漫。本文从产品经理和研发两个…

2026/7/3 14:18:39阅读更多 →
审计来了,数据权限全开——审计走了,怎么确保权限全部关掉?

审计来了,数据权限全开——审计走了,怎么确保权限全部关掉?

引言:审计结束三个月了,审计员的权限还没关某城商行每年按照监管要求开展至少一次数据安全审计。审计期间,内审部门需要抽样检查各类业务数据——交易流水、客户信息、员工操作日志、权限配置记录。这些数据分布在不同系统中,审计…

2026/7/3 14:38:35阅读更多 →
LV3296与PIC18F45K22的UART通信与USB扩展方案

LV3296与PIC18F45K22的UART通信与USB扩展方案

1. LV3296与PIC18F45K22的硬件搭档解析在嵌入式数据采集系统中,LV3296条形码扫描模块与PIC18F45K22微控制器的组合堪称经典搭配。LV3296作为一款工业级条码扫描头,其核心是一颗高性能CMOS图像传感器,配合专用解码芯片,能自动识别包…

2026/7/3 0:03:41阅读更多 →
AI初创生存指南:6个月完成可信度验证闭环

AI初创生存指南:6个月完成可信度验证闭环

1. 这不是“逆袭指南”,而是一份AI初创公司真实生存手记“How To Beat Odds As an AI Startup?”——这个标题乍看像一句热血口号,但在我带过7个从0到1的AI产品团队、亲手踩过融资失败、技术债崩盘、客户POC卡在最后一公里等23类典型坑之后,…

2026/7/3 0:03:41阅读更多 →
多模态+推理链+RAG 2.0+智能体:工业级AI系统落地四支柱

多模态+推理链+RAG 2.0+智能体:工业级AI系统落地四支柱

1. 这不是又一篇“AI趋势速览”,而是一份实操者手记:当多模态、推理链、检索增强与智能体协作真正撞进工程现场“LAI #73”这个编号本身就像一个暗号——它不属于某家大厂的白皮书,也不是学术会议的议程表,而是长期泡在模型训练集…

2026/7/3 0:03:41阅读更多 →
YOLOv8推理性能优化:从1.2FPS到35FPS的全链路加速实践

YOLOv8推理性能优化:从1.2FPS到35FPS的全链路加速实践

如果你在部署 YOLOv8 时,发现推理速度只有可怜的 1-2 FPS,而别人的演示视频却能跑到 30 FPS 以上,那么问题很可能不在模型本身,而在于你的整个处理链路。很多开发者拿到一个训练好的 YOLOv8 模型后,会直接使用官方示例…

2026/7/3 1:12:46阅读更多 →
Coze与Dify对比指南:低代码AI应用开发从入门到实战

Coze与Dify对比指南:低代码AI应用开发从入门到实战

1. 从零到一:为什么你需要了解 Coze 和 Dify?如果你对 AI 应用开发感兴趣,但一看到“大模型”、“智能体”、“工作流”这些词就头疼,觉得门槛太高,那这篇文章就是为你准备的。很多开发者,包括我自己&#…

2026/7/3 1:36:36阅读更多 →
AI生图工具怎么选?2026年6月版实测对比

AI生图工具怎么选?2026年6月版实测对比

做自媒体的朋友应该都有体会:配图一直是个让人头疼的问题。2026年,AI生图工具已经非常成熟了,但工具太多反而不知道怎么选。以下是截至2026年6月我对主流AI生图工具的实测对比。Midjourney V8.1:速度之王2026年6月11日&#xff0c…

2026/7/3 2:08:15阅读更多 →