Java单例模式:双检锁陷阱与最佳实践

发布时间:2026/10/7 20:52:39

Java单例模式:双检锁陷阱与最佳实践 老实说双重检查锁在Java界用的人多出锅的也多。干嘛非得采用双重检查呢, 是由于我们存有偷懒的想法, 没错, 确实是偷懒, 同步所产生的开销很大, 因而想着让同步仅在必要的情形下才触发, 这种必要情形便是 “实例还未曾被创建” 的时候, 然而在早年年头的 Java 版本当中这事儿事实上是存在不少坑的。先看代码——经典的双重检查写法大家面试背得都很熟public class Singleton { privatevolatilestatic Singleton instance; private Singleton() {} public static Singleton getInstance() { if (instance null) { // 第一次检查 synchronized (Singleton.class) { if (instance null) { // 第二次检查 instance new Singleton(); } } } return instance; } }关注要点, 这个是必定要有的, 倘若没有, 那么你所拥有的这种双检锁便是无效的。怎么会这么讲, 究竟是基于何种缘由才这般表述, 这是由于在JVM创建新对象之际, 实际上是开展过诸多繁杂多样的额外操作的。难道你会认为仅仅一句 new ();就全然是单一步骤的操作行为么, 抱持这种想法可就大错特错过于幼稚天真了, 事实上它确切无疑能够被拆解划分成为恰好三步的:分配内存调用构造函数将内存地址赋给那JVM, 它是存在指令重排序这种情况的, 有可能先把引用给赋了值, 之后才去初始化对象。你说这是不是很坑? 如此一来, 某个线程所拿到的就极有可能是个“半成品”。这就好比你早上到食堂去打饭, 阿姨递给你一个尚未熟透的鸡腿, 还说,“这是熟的”你敢去吃吗?自JDK 1.5起始, 语义得以强化, 使得写入操作的“-”这种关系得到保障, 进而才致使此方法变得安全且可靠。但话又说回来, 这么个写法, 我着实不建议在线上系统当中使用。为何呢? 因为它太易于出现差错了, 特别是当你所在的团队里存在实习生的情况下……我一般怎么做呢直接上静态内部类public class Singleton { private Singleton() {} privatestaticclass Holder { privatestaticfinal Singleton INSTANCE new Singleton(); } public static Singleton getInstance() { return Holder.INSTANCE; } }这方式的优点显而易见你说是不是香当然了, 并非是所有的人都对这一套青睐有加, 特别是存在一些人, 一旦瞧见内部类便会萌生出密集恐惧症, 如此情况下, 那你能够思索借助枚举去达成单例:public enum Singleton { INSTANCE; public void doSomething() { // 方法逻辑 } }在Java里边, enum天然便属于那种单例形态的, 针对反序列化以及反射攻击它皆能够阻挡住当然, 除非你运用极具邪门意味的那种招数, 简直就好似开了挂一般。可是, 针对这种方式, 我通常仅仅是在那些标示为“真·单例”的场景之内采用它, 比如像那种用于注册中心或者线程池管理器这样情况, 毕竟, 枚举这个东西灵活性不是很强, 扩展性能方面也稍有点缺乏意趣。那在什么样的时候, 才应该去使用双重检查锁呢? 只是在你能够清晰明确地知道, 这个对象的构造过程是极为昂贵的, 并且懒加载会带来明显显著的受益的场景之下。好比弄个缓存系统, 初始化时得跑到数据库load一堆配置, 在这种情形下懒加载是具备意义的。不然就别去折腾这一套——直接通过静态初始化或者内部类来处理, 如此开发效率以及安全性都会更高。现在有些人连写个线程安全单例都喜欢整成 Bean……反正, 都是能够去进行管理的, 你做一个, 再配合一个Scope(), 这样不就把事情完成了?并不是说这不行, 而是在于你把原本简单的问题给复杂化了。单例, 本来JVM自身是能够将其搞定的, 可你却非要弄出IOC来进行托管, 这情形是不是隐隐有些吃饱了却没事找事, 存在那样一种嫌疑?据此得出的结论相当简明: 技术乃是用来为业务提供服务的, 切莫只为了“显摆帅气”而去施展一些充满玄技色彩的设计, 最终导致团队承担相关责任, 而你自己却要承担主要责任, 这类事情我可是见识过许多回了……
延伸阅读

更多相关文章

2026/10/7 9:36:25

redis【msb 2026金三银四redis上】

1、redis和hashmap在结构上有什么区别?1、定位一个数据库一个数据结构2、单机和分布式3、支持的各种数据类型上面2、redis有哪些数据类型?底层如何实现?redis的所有基本数据类型都使用StringString---set user:1 666Hash---hset user:2 name …

2026/10/8 8:33:21

C++ 实现读写锁的代码详解

前言读写锁(reader-writer lock)要解决的是一类很常见的并发矛盾:共享数据被读的次数远远多于 被写的次数。用普通的 std::mutex,两个读者明明互不干扰,却必须排队,白白浪费了并行度; 而用读写锁…

2026/10/8 8:33:21

UIUC CS241系统编程中文讲义:从进程线程到内存同步的实战指南

简介:面向系统编程学习者的UIUC CS241中文讲义翻译项目,基于美国伊利诺伊大学厄巴纳-香槟分校经典课程整理而成,适合需要系统理解进程、线程、虚拟内存、同步与并发等底层机制的开发者参考。该资源为ApacheCN开源社区维护的校对版&#xff0c…

2026/10/8 8:33:21

DLL修复工具免费版靠不住?系统命令+运行库才是根本

简介:这款DLL修复工具面向因系统动态链接库缺失或损坏而导致软件无法运行的普通用户与维护人员,能够自动扫描并一键修复常见DLL错误,适用于游戏启动失败、办公软件报错等典型场景。压缩包共192个文件,约99.32MB,核心包…

2026/10/8 8:33:21

阿里云短信接口Demo全解析:从调用链路到生产落地

简介:这份压缩包定位为阿里云短信服务在PHP环境中的集成示例,面向需要快速接入短信验证码、系统通知或营销消息的网站开发者。压缩包整体大小约三点三五兆字节,内含阿里云官方短信服务的PHP开发包调用示例,完整演示了从配置访问密…

2026/10/8 8:33:21

Linux服务器RAR工具部署与命令行实战指南

简介:这是一款面向Linux 64位(x86_64)系统的RAR压缩工具测试版,对应版本6.1.b1,主要解决在纯命令行环境中创建、解压、修复RAR档案的需求,适合系统管理员、运维工程师以及经常处理跨平台压缩包的开发者。包…

2026/10/8 8:28:20

QuickBlue:AI应用工程化底座的实践与演进

1. QuickBlue 不是另一个“AI平台”,而是一套被低估的工程化底盘QuickBlue 这个名字刚出现在我视野里时,我下意识点开几个技术社区帖子,发现多数讨论都卡在“它是不是又一个大模型封装壳”上——这恰恰暴露了当前企业落地AI最深的误区&#x…

2026/10/5 6:32:56

Jev+Agent接管浏览器:browser-use实战与jev-ultrafast性能优化

1. 从“Jev”说起:为什么我要把Agent接进浏览器“Jev”这个词最近在圈子里出现的频率越来越高,很多人第一次听到会以为是某个新模型的名字,其实它更像是一种思路——把Jev模型的能力当作底座,通过Agent的方式去接管浏览器&#xf…

2026/10/7 8:18:33

多智能体集群实战:DeepAgents编排、MCP与A2A协议及Skills体系

1. 从"单兵作战"到"集群协同":多智能体编排到底在解决什么问题如果你最近在折腾 Agent 相关的东西,大概率会有一种感觉:单个 Agent 能做的事情,其实很快就摸到天花板了。你给它一个提示词,挂几个工…

2026/10/8 6:05:44

无源低通滤波器设计实战:从RC到LC,手把手教你避开那些坑

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/8 0:02:17

自然数立方等于连续奇数之和:从证明到编程验证

十几年来我一直游走在数学科普和编程教学这两块内容之间,对“看起来像魔法、拆开全是数学”的结论总是格外敏感。最近翻资料时又撞见一句话:任何一个自然数 m 的立方,都可以写成 m 个连续奇数之和。2 的立方等于 3 加 5,3 的立方等…

2026/10/8 0:02:17

C#上位机SSH连接实战:用SSH.NET补齐超时、批量与密钥认证

简介:这是一份基于 C# 开发的 SSH 连接功能半成品工程,原本作为另一个主项目的子功能模块,现独立打包分享。工程采用 WinForms 界面,包含源码、解决方案、安装部署工程、NuGet 依赖包及说明文档,适合正在做远程连接、网…

2026/10/8 0:02:17

Java SpringBoot一体化智能售后系统设计与实现全解析

毕业设计年年做,Java Web 方向的题目翻来覆去就那么几个,但“一体化智能售后系统”这个题,每次看到我都觉得值得认真聊一聊。它不是一个简单 curd 堆出来的管理系统,而是把客户、工单、派单、处理、回访、统计整条链路串起来的一套…

还想了解更多?直接咨询顾问

免费诊断 + 免费方案 + 透明报价。

全国咨询热线400-8866-253
免费获取方案
☎咨询二维码 ☎ ↑