当前位置: 首页 > news >正文

单例模式全解析:5种写法 + 破坏与防护

文章目录

  • 什么是单例模式?
  • 实现方式
    • 饿汉式
    • 懒汉式
      • 方式一(线程不安全)
      • 方式二(同步方法)
      • 方式三(双重检查锁 DCL)
    • 枚举

什么是单例模式?

保证一个类在全局只有一个实例,并提供一个全局访问点。
适用场景:配置类、连接池、日志对象等全局唯一的资源。

实现方式

饿汉式

类加载时就创建实例,天然线程安全。

classHungrySingleton{privatestaticfinalHungrySingletoninstance=newHungrySingleton();privateHungrySingleton(){}publicstaticHungrySingletongetInstance(){returninstance;}}

优点:简单,线程安全
缺点:不管用不用都会创建对象,可能浪费内存

懒汉式

方式一(线程不安全)

classLazySingleton{privatestaticLazySingletoninstance;privateLazySingleton(){}publicstaticLazySingletongetInstance(){if(instance==null){instance=newLazySingleton();}returninstance;}}

延迟创建对象,但多线程下可能创建多个实例,线程不安全。

方式二(同步方法)

classSafeThreadLazySingleton{privatestaticSafeThreadLazySingletoninstance;privateSafeThreadLazySingleton(){}publicstaticsynchronizedSafeThreadLazySingletongetInstance(){if(instance==null){instance=newSafeThreadLazySingleton();}returninstance;}}

加锁保证线程安全,但每次获取对象都要经过锁竞争,性能不好。

方式三(双重检查锁 DCL)

classDCLLazySingleton{privatestaticvolatileDCLLazySingletoninstance;privateDCLLazySingleton(){}publicstaticDCLLazySingletongetInstance(){if(instance==null){synchronized(DCLLazySingleton.class){if(instance==null){instance=newDCLLazySingleton();}}}returninstance;}}

第一个 if:判断对象是否已经创建,避免每次都进入同步块,提升性能。

第二个 if:高并发下第一个 if 可能同时放进来多个线程(如 A、B、C),它们被锁阻塞。A进入临界区创建了对象后退出,B 或 C 再进来时,第二个 if 告诉它对象已存在,直接返回。

volatile 的作用:防止指令重排序。new 一个对象分三步:① 分配内存 → ② 初始化对象 → ③将引用指向内存地址。JVM 可能将顺序优化为①③②,此时另一个线程拿到的是未初始化完成的对象,产生空指针问题。volatile禁止这种重排序,保证对象完整创建后才对外可见。

枚举

enumEnumSingleton{INSTANCE;publicvoiddoSomething(){// 业务方法}}
// 使用EnumSingleton.INSTANCE.doSomething();

简洁优雅,属于饿汉式。是唯一不会被反射和反序列化破坏的单例实现,Josh Bloch 在《Effective Java》中推荐的方式。

除枚举外,其他单例都可以通过以下方式强行创建新实例:

  • 反射:Constructor.setAccessible(true) 绕过私有构造器
  • 反序列化:对象实现 Serializable 后,反序列化会创建新对象

枚举在 JVM 层面做了保护,这两种方式对它均无效。

http://www.jsqmd.com/news/579467/

相关文章:

  • DPU协议卸载功能详解
  • OpenClaw+Phi-3-vision-128k-instruct安全方案:敏感数据本地化处理指南
  • 基于MATLAB的悬臂梁前3阶固有频率和振型求解(假设模态法、解析法、瑞利里兹法)
  • SenseVoice-Small ONNX精彩案例分享:10分钟会议录音→带标点可编辑文本
  • 2026年4月深度横评|五款主流远程控制软件,到底谁才是你的“设备桥梁”?
  • Go 并发锁的底层实现原理
  • OpenClaw压力测试:Qwen3-14B在并发请求下的响应延迟分析
  • 服务器安全审计与入侵检测
  • 深入探索Java JPA中的CriteriaQuery
  • OpenClaw性能调优:降低Phi-3-mini-128k-instruct长任务token消耗的技巧
  • 颜色代码选择助手源码前端开发HEX颜色值十六进制一键复制创意设计色彩搭配软件工具+安卓APP
  • PyTorch 2.8高性能镜像案例分享:RTX 4090D上FlashAttention-2加速LLM微调实测
  • API 测试工具:Postman, Rest-Assured
  • 【Guava】并发编程ListenableFutureService
  • Kandinsky-5.0-I2V-Lite-5s图生视频实战教程:5秒短视频一键生成(RTX4090D友好)
  • SEO_避开这些SEO误区让你的优化更高效
  • MeteorSeed
  • 基于S7-1200PLC的物业供水控制系统设计》 PLC触摸屏,图纸,博图16 一、设计任务书...
  • C++ STL 容器线程安全机制研究
  • 彻底搞懂大模型“图谱推理”底层逻辑!TPAMI神作全解(非常详细)
  • 像素剧本圣殿效果展示:8-Bit像素风界面中实时生成的动画分镜脚本
  • Graphormer部署教程:Docker Compose编排Graphormer+Redis缓存服务
  • OpenClaw私人健身教练:Qwen2.5-VL-7B分析运动视频与生成计划
  • 忍者像素绘卷实战案例:16-Bit忍者风海报生成全流程详解
  • OpenClaw+千问3.5-9B爬虫方案:智能解析与数据入库
  • 网络资源爬取代码分享
  • 2026年靠谱的东台冷库门封/装卸货门封厂家精选合集 - 品牌宣传支持者
  • 基于LS-DYNA ANSA的汽车碰撞CAE联合仿真教程:软件操作与模型搭建
  • AI Agent火了,但你的基础设施真的能扛住吗?先看清这3个代价
  • OpenClaw跨设备控制方案:百川2-13B-4bits量化版中继服务搭建