网易首页 > 网易号 > 正文 申请入驻

99%程序员写单例都栽过这个坑, senior devs 的解法让代码量少一半

0
分享至

一个看似简单的设计模式,Stack Overflow 上却攒了 4000+ 个"为什么我的单例失效了"的提问。

单例模式(Singleton Pattern)被程序员称为"最容易写错的设计模式",没有之一。面试时八股文背得滚瓜烂熟,生产环境一跑就露馅。线程安全问题、反射攻击、序列化漏洞——新手写的单例代码,往往带着这三颗定时炸弹上线。

我见过最离谱的 case:某电商大促期间,库存服务因为单例被重复初始化,导致超卖 3000 多单。事后复盘,开发者在单例里加了 `synchronized` 关键字,却忘了指令重排序的坑。这就像是给门上了锁,但窗户还敞着。

初级程序员的"标准错误答案"

打开任意一篇中文技术博客,教你写单例的第一种写法大概率是"饿汉式":

```java public class Singleton { private static Singleton instance = new Singleton(); private Singleton() {} public static Singleton getInstance() { return instance; } } ```

这种写法线程安全,但问题在于:类加载时就初始化,不管用不用都占着内存。对于启动耗时敏感的大型应用,这相当于提前把全家桶点好,哪怕你只想要一杯可乐。

于是新手转向"懒汉式",加个 `if (instance == null)` 判断延迟加载。多线程环境一压测,直接冒出多个实例。赶紧套上 `synchronized`,性能又断崖式下跌——每次获取实例都要排队,高并发场景下这行代码就是瓶颈。

双重检查锁定(Double-Checked Locking)看似解决了性能和线程安全的矛盾,但 `volatile` 关键字漏写的概率,堪比忘记关煤气阀。没有内存屏障保证,指令重排序会让另一个线程拿到未完全构造的对象,然后调用一个空指针方法。

99% 的初级开发者,都停留在"能跑就行"的阶段。单元测试通过,代码评审没人细看,直到生产环境炸雷。

Senior Devs 的解法:从"造轮子"到"用现成"

真正写过百万行代码的老手,第一反应不是"怎么写个完美的单例",而是"为什么需要单例"。

Google 的 Java 开发规范里有个冷知识:单例本质上是一种全局状态,而全局状态是测试的天敌。依赖注入框架(Dependency Injection)成熟之后,Spring 容器管理的 Bean 默认就是单例,而且线程安全、生命周期可控、支持 AOP 增强。

「我们内部已经禁止手写单例了。」某头部云厂商中间件团队的技术负责人告诉我,「除非你在写框架级代码,否则用 Spring 的 `@Singleton` 或者 Guice 的 Provider,比自己实现可靠一百倍。」

如果确实需要裸写 JVM 层面的单例, senior devs 的选项也变了。枚举单例(Enum Singleton)从 Java 5 开始就被《Effective Java》作者 Joshua Bloch 推荐:

```java public enum Singleton { INSTANCE; // 业务方法 } ```

三行代码,天然防反射、防序列化攻击、线程安全由 JVM 保证。这就像是买保险,别人还在对比条款,你已经选了理赔最痛快的那个。

更激进的方案来自 Kotlin:用 `object` 关键字声明的类,编译器直接生成单例。没有样板代码,没有线程安全隐患,语法糖甜到腻。

比写法更重要的:单例的"退出策略"

新手关注"怎么创建",老手关注"怎么销毁"。

单例持有数据库连接池、缓存客户端、线程池等资源时,应用重启或热部署阶段如果清理不干净,就是内存泄漏和连接数暴涨的元凶。某金融系统的支付网关曾经因此导致连接池耗尽,交易成功率从 99.9% 跌到 87%。

Java 的 `Runtime.addShutdownHook`、Spring 的 `@PreDestroy`、或者实现 `Closeable` 接口配合 try-with-resources,都是 senior devs 会主动考虑的退出机制。写单例时先想怎么关,比先想怎么开更重要。

另一个被忽视的维度是类加载器隔离。在 Tomcat 热部署场景下,如果单例被父类加载器持有,而业务代码被 WebApp 类加载器加载,重复部署会导致旧实例无法回收。这个问题在微服务架构里不常见,但在传统 Java EE 遗留系统中,排查起来能让人掉光头发。

2024 年,单例模式正在"退环境"

云原生和 Serverless 架构的普及,让"全局唯一实例"这个假设本身变得可疑。

容器水平扩容时,每个 Pod 都有自己的 JVM 进程,单例变成了"每个实例里的单例"。如果需要跨进程唯一,就得引入分布式锁或一致性哈希——这时候你面对的问题,已经不是设计模式能解决的。

无状态服务(Stateless Service)成为主流架构原则后,把状态外移到 Redis、Etcd 或数据库,比在代码里维护单例更符合 12-Factor 规范。某跨境电商的技术 VP 跟我聊过,他们去年重构核心交易链路时,一口气干掉了 47 个手写单例,P99 延迟下降了 23%。

函数式编程的兴起也在改写游戏规则。Scala 的 `object`、Rust 的 `lazy_static`、甚至 Java 的 `Supplier` 接口配合 `memoize` 操作,都在用更声明式的方式表达"只计算一次"的语义,而不必套用 GoF 的类结构。

Stack Overflow 2023 年度开发者调查显示,设计模式相关问题的浏览量同比下降 18%。这不是说设计模式过时了,而是现代语言和框架把最佳实践封装进了语法和库,普通开发者不再需要亲自操刀。

回到开头那个超卖 3000 单的案例。事后团队复盘,技术负责人把单例实现换成了枚举类型,同时在架构评审环节加了"禁止手写单例"的 checklist。三个月后,同一场大促,库存服务零故障。

你代码库里还有手写的单例吗?最近一次 code review,有人问过它该怎么销毁吗?

特别声明:以上内容(如有图片或视频亦包括在内)为自媒体平台“网易号”用户上传并发布,本平台仅提供信息存储服务。

Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.

相关推荐
热点推荐
李嘉欣现身伦敦街头被路人偶遇,顶级骨相美到发光完全不像55岁

李嘉欣现身伦敦街头被路人偶遇,顶级骨相美到发光完全不像55岁

喜欢历史的阿繁
2026-04-24 11:57:41
利物浦老板芬威集团展现冷酷一面,解雇教练及五名工作人员

利物浦老板芬威集团展现冷酷一面,解雇教练及五名工作人员

绿茵情报局
2026-04-27 02:32:19
近10年崩得最狠的专业:从年薪几十万到月薪两千五!

近10年崩得最狠的专业:从年薪几十万到月薪两千五!

灯锦年
2026-04-21 13:28:31
“崩老头”现象:00后如何收割中年男性

“崩老头”现象:00后如何收割中年男性

流苏晚晴
2026-04-25 16:31:35
两兄弟公司破产的真相!小鸡嘴女星复出的代价!

两兄弟公司破产的真相!小鸡嘴女星复出的代价!

八卦疯叔
2026-04-25 11:34:30
落难的凤凰不如鸡,多位明星无戏可拍,沦落到给景区打工,太心酸

落难的凤凰不如鸡,多位明星无戏可拍,沦落到给景区打工,太心酸

秋姐居
2026-03-29 22:00:48
有趣,穆西亚拉赛后拉着奥利塞跟他自拍,奥利塞冷脸竖中指

有趣,穆西亚拉赛后拉着奥利塞跟他自拍,奥利塞冷脸竖中指

懂球帝
2026-04-26 15:47:06
千年难遇的美人,太漂亮了,没有一点毛病,太完美了

千年难遇的美人,太漂亮了,没有一点毛病,太完美了

情感大头说说
2026-04-24 12:46:24
掘金濒临出局!约基奇回应G4冲突:绝不后悔,谁让他不讲武德!

掘金濒临出局!约基奇回应G4冲突:绝不后悔,谁让他不讲武德!

仰卧撑FTUer
2026-04-26 14:38:10
唏嘘!郑钦文74天内两次被世界第2逆转 离谱9次双误 又一苦主诞生

唏嘘!郑钦文74天内两次被世界第2逆转 离谱9次双误 又一苦主诞生

我爱英超
2026-04-27 05:41:50
天降惩罚,日本才遭强震,又来山火肆虐!民众跪求中国救援

天降惩罚,日本才遭强震,又来山火肆虐!民众跪求中国救援

小兰聊历史
2026-04-26 18:15:33
常规赛龙、季后赛虫!骑士89-93再输猛龙!谁是输球的罪魁祸首?

常规赛龙、季后赛虫!骑士89-93再输猛龙!谁是输球的罪魁祸首?

毒舌NBA
2026-04-27 05:31:31
伊朗副议长:穆杰塔巴下令霍尔木兹海峡不得恢复战前状态

伊朗副议长:穆杰塔巴下令霍尔木兹海峡不得恢复战前状态

新京报
2026-04-26 07:47:12
美股持续新高,我的账户今年49%了

美股持续新高,我的账户今年49%了

振阳笔记
2026-04-26 22:34:51
美国海军部长达里尔・考德尔公然喊话,要求中国立刻停止建造军舰

美国海军部长达里尔・考德尔公然喊话,要求中国立刻停止建造军舰

安安说
2026-04-26 11:04:42
立陶宛总统发声:中方想重建关系必须展现诚意!

立陶宛总统发声:中方想重建关系必须展现诚意!

橙色书卷
2026-04-25 20:46:11
宁波一高速隧道内车辆起火烟雾弥漫,大量汽车堵在隧道内,众人纷纷弃车跑出洞口,官方回应

宁波一高速隧道内车辆起火烟雾弥漫,大量汽车堵在隧道内,众人纷纷弃车跑出洞口,官方回应

极目新闻
2026-04-26 22:31:28
陈伟霆公开靠吃馒头减肥,一顿只吃一个馒头,成功瘦了20斤下来!

陈伟霆公开靠吃馒头减肥,一顿只吃一个馒头,成功瘦了20斤下来!

螃蟹记录站
2026-04-26 23:50:59
穆帅大利好,争亚对手犯错,1:1平局,丢掉2分;本菲卡稳住第2位

穆帅大利好,争亚对手犯错,1:1平局,丢掉2分;本菲卡稳住第2位

福酱的小时光
2026-04-27 06:04:14
“只顾自己纹眉,不管女儿死活?”14岁女孩生日照,脸上全是槽点

“只顾自己纹眉,不管女儿死活?”14岁女孩生日照,脸上全是槽点

蝴蝶花雨话教育
2026-04-25 00:45:03
2026-04-27 08:04:49
摸鱼算法
摸鱼算法
致力于用最前沿的AI技术,换取更多发呆时间的三十岁青年。
1722文章数 17关注度
往期回顾 全部

科技要闻

打1折!DeepSeek输入缓存降价

头条要闻

高市用双语表态:得知特朗普总统安然无恙 我如释重负

头条要闻

高市用双语表态:得知特朗普总统安然无恙 我如释重负

体育要闻

森林狼3比1掘金:逆境中杀出了多孙穆?!

娱乐要闻

仅次《指环王》的美剧,有第二季

财经要闻

事关新就业群体,中办、国办发文

汽车要闻

预售19.38万元起 哈弗猛龙PLUS七座版亮相

态度原创

时尚
亲子
艺术
家居
军事航空

比阔腿裤还时髦?今年夏天一定要有“这条裤子”,减龄又松弛

亲子要闻

爸爸买的餐椅太好了,早知道早买了#餐椅 #宝宝板凳 #宝宝吃饭 #宝妈推荐

艺术要闻

72米舞台被拆!华晨宇这次玩文旅,翻车了!

家居要闻

自然肌理 温润美学

军事要闻

伊朗总统:不会在压力、威胁下进行谈判

无障碍浏览 进入关怀版