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

Java多线程学习(六)

再整理一下单例模式的饿汉与懒汉,还有指令重排序的知识点


在并发编程中,单例模式(Singleton Pattern)的实现方式直接反映了开发者对线程安全、加锁粒度和编译器优化的理解。

一、 饿汉模式:简单但“固执”

饿汉模式(Eager Initialization)在类加载时就完成了初始化。

classSingleton{privatestaticSingletoninstance=newSingleton();privateSingleton(){}publicstaticSingletongetInstance(){returninstance;}}
  • 优点:绝对的线程安全。JVM 在加载类时会保证静态变量的初始化是同步的。
  • 缺点:不支持懒加载。如果该实例占用内存大且程序运行期间从未被使用,就会造成资源浪费。

二、 懒汉模式:性能与安全的博弈

classSingletonLazy{privatestaticvolatileSingletonLazyinstance=null;privatestaticObjectlocker=newObject();// 第一次使用这个实例的时候, 才会创建这个实例. 创建时机是更晚的.publicstaticSingletonLazygetInstance(){if(instance==null){synchronized(locker){if(instance==null){instance=newSingletonLazy();}}}returninstance;}}

懒汉模式(Lazy Initialization)的核心思想是:不到万不得已,绝不创建对象。

1. 为什么需要“双重校验锁”(Double-Checked Locking)?

给出的代码中使用了if (instance == null)嵌套synchronized。为什么要判断两次?

  • 第一次判断(外层 if):为了效率
    如果不加这个判断,每次调用getInstance()都要先竞争锁。锁的竞争是昂贵的,而实际上对象创建后,所有的getInstance操作都只是读取,根本不需要锁。有了这一层,实例创建后,线程可以直接返回,不用排队。
  • 加锁(synchronized):为了原子性
    防止多个线程同时通过了第一层判断,导致创建出多个实例。
  • 第二次判断(内层 if):为了正确性
    当 A、B 两个线程都通过了外层判断,A 拿到锁创建了对象,随后释放锁。此时 B 拿到锁进入内部,如果不进行第二次判断,B 会再次创建一个新对象,单例宣告失败。

三、 核心悬疑:为什么必须加volatile

在代码中,private static volatile SingletonLazy instance里的volatile是灵魂所在。如果没有它,程序可能会在极端高并发下崩溃。

指令重排序的“背刺”

当我们执行instance = new SingletonLazy();时,JVM 层面其实拆分成了三步:

  1. 分配内存空间(给对象找个地儿)。
  2. 执行构造方法(初始化对象,填入数据)。
  3. 将引用指向内存空间(把变量名和地址关联起来)。

由于编译器优化,这三步可能变成1 -> 3 -> 2
想象一下:

  1. 线程 A 执行了 1 和 3,此时instance已经非空了(指向了一块地址),但2(初始化)还没完成
  2. 就在这时,线程 B 进来了,执行外层的if (instance == null)
  3. 线程 B 发现instance不为空,直接return instance拿去用了。
  4. 悲剧发生:线程 B 拿到的其实是一个“半成品”对象(还没初始化完),使用它会直接报错。

volatile的作用
它在此处通过内存屏障禁止了上述指令重排序,保证了“初始化”一定发生在“赋值给引用”之前。


四、 总结:懒汉模式的三个要素

要写出一个完美的多线程懒汉单例,必须满足:

  1. 构造方法私有化:防止外部new
  2. 双重 if 判断:兼顾性能与安全。
  3. volatile 修饰:防止指令重排导致的“半成品”对象问题。

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

相关文章:

  • 20253312 实验一《Python程序设计》实验报告
  • 论文写作新利器:书匠策AI,让数据分析变得像呼吸一样自然!
  • 2026年生鲜配送软件应用白皮书 中央厨房数字化剖析 - 优质品牌商家
  • 2026.3.23
  • 智能文字提取新标杆:Text-Grab本地化OCR工具全解析
  • LLM批处理系统:自适应并发控制;断点续传与进度追踪
  • 书匠策AI:论文数据分析的“超级外挂”,让学术研究如虎添翼
  • CloudWatch 告警实战:CPU 飙了自动扩容,账单超了 Slack 通知
  • 2026年水泥预制烟道厂家实力推荐榜:矩形/机制/装配式/锅炉专用烟道,精选耐用建材与专业工艺解析 - 品牌企业推荐师(官方)
  • 2026年3月郑州搬家公司最新推荐:金水区搬家、上街区搬家、惠济区搬家、荥阳搬家、新密搬家、新郑搬家公司选择指南 - 海棠依旧大
  • 2026年体育学论文降AI率工具推荐:运动训练方向同学看过来
  • 论文写作新利器:书匠策AI,让数据分析“智”在必得!
  • Electron应用安装包定制指南:如何用NSH脚本打造个性化安装界面(附完整代码示例)
  • 川内制造业短期工招聘服务品牌评测报告:就近安排找工作/工厂劳务外包派遣/工厂劳务派遣外包/工厂直招找工作/当天入职劳务派遣/选择指南 - 优质品牌商家
  • 省电神器!STM32G030的ADC低功耗采样方案:TIMER+DMA+HAL库全配置指南
  • 书匠策AI:论文数据分析的“超级外挂”,让科研之路畅通无阻
  • PD-L1重组兔单抗如何助力肿瘤免疫治疗的机制研究与疗效评估?
  • 2026化妆品源头工厂趋势:从规模到价值的跃迁 - 速递信息
  • # 发散创新:用 WebSocket 实现实时聊天系统的全链路架构设计
  • 企业在豆包做AI推广联系哪家公司?专业服务商深度解析 - 品牌2026
  • vxe-table列头合并避坑指南:从基础配置到高级动态调整
  • 8大需求分析软件选型指南:2026文档自动化新趋势解读
  • # 20253202 2025-2026-2 《Python程序设计》实验1报告
  • 基于太赫兹时域光谱的烟草含水量与厚度深度学习识别模型
  • 20252211 2025-2026-2 《Python程序设计》实验1报告
  • Ollama 非C盘部署
  • 避坑指南:Windows搭建Turn服务器常见问题及解决方案
  • 【灵神题单·贪心】3010. 将数组分成最小总代价的子数组 I | Java
  • 成都施工吊篮租赁优选指南适配多场景需求:成都工地吊篮租赁/成都建筑吊篮租赁/成都施工吊篮租赁/成都电动吊篮租赁/选择指南 - 优质品牌商家
  • CSS3文字闪烁效果实战:3种方法让你的网页标题更吸睛(附完整代码)