【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/18 1:43:33阅读更多 →
告别海外账号烦恼: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/17 6:59:47阅读更多 →
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/17 23:17:38阅读更多 →
UVa 694 The Collatz Sequence

UVa 694 The Collatz Sequence

题目描述 给定一个正整数 AAA 和限制值 LLL,根据 Collatz\texttt{Collatz}Collatz 序列生成规则: 若 A1A 1A1,停止;若 AAA 为偶数,则 AA/2A A / 2AA/2;若 AAA 为奇数,则 A3A1A 3A 1A3A1。 要…

2026/7/18 13:33:04阅读更多 →
Coze变量命名规范与记忆持久化最佳实践:ISO/IEC 29110认证团队验证的7条硬性标准

Coze变量命名规范与记忆持久化最佳实践:ISO/IEC 29110认证团队验证的7条硬性标准

更多请点击: https://intelliparadigm.com 第一章:Coze变量与记忆功能的架构本质与设计哲学 Coze 的变量与记忆系统并非简单的键值存储抽象,而是融合了对话生命周期管理、上下文感知推理与多粒度状态隔离的设计范式。其核心在于将“状态”视…

2026/7/18 13:33:04阅读更多 →
3D高斯语义占据预测:从LiDAR引导的可变形注意力到自动驾驶场景理解

3D高斯语义占据预测:从LiDAR引导的可变形注意力到自动驾驶场景理解

1. 从体素到高斯:为什么我们需要一种新的场景表示? 如果你最近在关注自动驾驶或者三维视觉领域,大概率会频繁听到“3D Gaussian Splatting”这个词。它最初在NeRF领域大放异彩,以其惊人的渲染质量和速度,几乎重塑了我们…

2026/7/18 13:33:04阅读更多 →
Beyond Compare 5密钥生成3种方法:告别评估模式错误的完整解决方案

Beyond Compare 5密钥生成3种方法:告别评估模式错误的完整解决方案

Beyond Compare 5密钥生成3种方法:告别评估模式错误的完整解决方案 【免费下载链接】BCompare_Keygen Keygen for BCompare 5 项目地址: https://gitcode.com/gh_mirrors/bc/BCompare_Keygen 你是否正在为Beyond Compare 5的"评估模式错误"而烦恼&…

2026/7/18 13:33:04阅读更多 →
Copilot企业版报价单暗藏的3个加价项:License绑定规则、API调用量阈值、审计日志附加费全解析

Copilot企业版报价单暗藏的3个加价项:License绑定规则、API调用量阈值、审计日志附加费全解析

更多请点击: https://kaifayun.com 第一章:Copilot企业版报价单暗藏的3个加价项:License绑定规则、API调用量阈值、审计日志附加费全解析 微软Copilot企业版(Copilot for Microsoft 365 Enterprise)在官方报价单中常以…

2026/7/18 13:33:04阅读更多 →
Linux内核调试实战:从GDB到QEMU全解析

Linux内核调试实战:从GDB到QEMU全解析

1. Linux内核调试概述 在Linux系统开发与维护过程中,内核调试是最具挑战性的任务之一。与用户空间程序调试不同,内核调试需要特殊的工具和方法,因为内核运行在特权级别,直接控制硬件资源,一旦出现问题可能导致整个系统…

2026/7/18 13:28:04阅读更多 →
VSCode TypeScript 环境配置对比:全局安装 vs 项目本地安装的4个关键差异

VSCode TypeScript 环境配置对比:全局安装 vs 项目本地安装的4个关键差异

VSCode TypeScript 环境配置对比:全局安装 vs 项目本地安装的4个关键差异当你在VSCode中启动一个新的TypeScript项目时,第一个技术决策往往从安装方式开始。这个看似简单的选择——全局安装还是项目本地安装——实际上会深刻影响你的开发流程、团队协作和…

2026/7/18 10:49:13阅读更多 →
智慧树刷课插件:5分钟实现自动化学习的智能助手

智慧树刷课插件:5分钟实现自动化学习的智能助手

智慧树刷课插件:5分钟实现自动化学习的智能助手 【免费下载链接】zhihuishu 智慧树刷课插件,自动播放下一集、1.5倍速度、无声 项目地址: https://gitcode.com/gh_mirrors/zh/zhihuishu 智慧树刷课插件是一款专为智慧树在线教育平台设计的Chrome浏…

2026/7/18 8:49:08阅读更多 →
Steam创意工坊下载器WorkshopDL:跨平台游戏模组获取的终极解决方案

Steam创意工坊下载器WorkshopDL:跨平台游戏模组获取的终极解决方案

Steam创意工坊下载器WorkshopDL:跨平台游戏模组获取的终极解决方案 【免费下载链接】WorkshopDL WorkshopDL - The Best Steam Workshop Downloader 项目地址: https://gitcode.com/gh_mirrors/wo/WorkshopDL 你是否在GOG或Epic Games Store购买了心仪的游戏…

2026/7/17 13:22:23阅读更多 →
从模糊意图到可执行指令:Claude PRD中Prompt Engineering与需求颗粒度的5级映射法则

从模糊意图到可执行指令:Claude PRD中Prompt Engineering与需求颗粒度的5级映射法则

更多请点击: https://kaifayun.com 第一章:从模糊意图到可执行指令:Claude PRD中Prompt Engineering与需求颗粒度的5级映射法则 在Claude驱动的产品需求文档(PRD)生成实践中,原始业务意图往往以自然语言片…

2026/7/18 0:00:14阅读更多 →
Cursor配置生成失效?3大隐藏陷阱+4行修复代码,资深工程师连夜整理的紧急补救清单

Cursor配置生成失效?3大隐藏陷阱+4行修复代码,资深工程师连夜整理的紧急补救清单

更多请点击: https://codechina.net 第一章:Cursor配置生成失效?3大隐藏陷阱4行修复代码,资深工程师连夜整理的紧急补救清单 Cursor 配置生成突然失效,是近期高频报障场景。表面看是 cursor.config.json 未更新或 LSP…

2026/7/18 0:00:14阅读更多 →
某智驾大牛创业

某智驾大牛创业

作者:钟声编辑:Mark出品:红色星际头图:智能驾驶图片据悉,国内某头部智驾公司端到端模型技术大牛Z投身创业,并且已经拿到融资。Z不仅是该头部公司内部最年轻的对标阿里P10级别技术负责⼈,更是业内…

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

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

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

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

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

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

2026/7/17 13:22:38阅读更多 →
AI生图工具怎么选?2026年6月版实测对比

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

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

2026/7/17 17:26:50阅读更多 →