为什么volatile++不是原子性的?

volatile++不是一个原子性操作,因为它包含三个步骤:读、自增、写。每个步骤本身原子,但组合起来非原子。volatile读写操作通过内存屏障确保可见性,但无法保证复合操作的原子性。解决方案包括使用synchronized或AtomicInteger/AtomicLong,后者利用CAS保证原子性。
摘要由CSDN通过智能技术生成

问题

在讨论原子性操作时,我们经常会听到一个说法:任意单个volatile变量的读写具有原子性,但是volatile++这种操作除外。

所以问题就是:为什么volatile++不是原子性的?

答案

因为它实际上是三个操作组成的一个符合操作。

  1. 首先获取volatile变量的值
  2. 将该变量的值加1
  3. 将该volatile变量的值写会到对应的主存地址

一个很简单的例子:

如果两个线程在volatile读阶段都拿到的是a=1,那么后续在线程对应的CPU核心上进行自增当然都得到的是a=2,最后两个写操作不管怎么保证原子性,结果最终都是a=2。每个操作本身都没啥问题,但是合在一起,从整体上看就是一个线程不安全的操作:发生了两次自增操作,然而最终结果却不是3。

分析

结合内存屏障这个概念对volatile的读写操作深入理解的话:

第一步:读

在第一步操作的指令后,会增加两个内存屏障:

  1. 在Volatile读操作后插入LoadLoad屏障,防止前面的Volatile读与后面的普通读重排序
  2. 在Volatile读操作后插入LoadStore屏障,防止前面的Volatile读与后面的普通写重排序

因此第一个指令和它后续的普通读写操作会被保证没有重排序来捣乱。通常是去内存中去读。

那么问题又来了,为什么通常去内存中读?

其实这个问题要说细的话可以很细,大概就两个关键点吧:

  1. volati
评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值