DCL单例中,实例变量为什么要用volatile修饰

本文探讨了在双重检查锁定(DCL)模式中使用volatile关键字的原因。通过分析对象实例化过程中可能出现的指令重排序问题,解释了volatile如何防止此类问题,并确保了线程间的可见性和一致性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

"乙"处对象实例化过程是非原子的,共分为3步:1.在内存中开辟一片内存区域 2.在这片内存区域中执行构造函数,实例化对象 3.instance引用指向这片内存区域。

假设instance变量没有用volatile关键字修饰,A、B两线程并发访问DCL.class的getInstance()方法,A先执行(时间上)。当线程A执行到"乙"处,上述3步操作可能被指令重排序为1->3->2,当线程执行了"3",还未执行"2"或"2"未完全执行完,此时 instance 不再是null(instance所指向区域已分配内存)。若此时轮到了线程B的时间片,B在"甲"处判断instance非空,就将instance返回了,而此时instance所指向的对象并未实例化或并未完全实例化,必将发生错误。

如果instance变量用volatile修饰,有两层效果:

  1. 禁止指令重排序优化:即不会出现指令执行顺序为1->3->2的情况,只能是1->2->3。当线程B执行到"甲"处,instance要么为null,要么指向已完全初始化了的对象(内存区域)。

  2. 保证instance变量的可见性(此部分内容涉及Java内存模型JMM,不熟悉的同学可以先去学习一下JMM):即当线程A成功初始化实例后,会将实例从线程A工作内存区域刷新到主存中,同时将其他线程(如线程B)工作内存区域中的instance无效化,使得其他线程只能从主存中获取instance对象。

 

所以,DCL中的实例变量有必要用volatile修饰。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值