[多线程]为什么volatile不能保证原子性而Atomic可以?

在网上看到了这篇文章,下面我给大家总结一下文章大概的意思

 

volatile可以在多线程的情况下,保证当值修改后会被其他的线程读取到最新的值,这得益于cpu的(内存屏障指令)

 

看了一下这个内存屏障指令,大概的意思是说当内存屏障指令发生后,cpu和编译器会收到这个命令,告诉cpu和编译器必须先于某条命令执行,后于某条指令执行,并且强制更新一次cpu缓存,这样其他线程就会拿到最新的值。

 

单单是这么看,好像volatile可以保证数据的原子性,但是我们再来仔细了解一下volatile的执行步骤:

1)读取volatile变量值到local;

2)增加变量的值;

3)把local的值写回,让其它的线程可见。

 

这三步对应到内存屏障指令里,是这样的:

 首先在第一步发生之前,也就是读操作发生之前,会插入一条读屏障指令这意味着如果你对一个volatile字段进行写操作,你必须知道:

     1、一旦你完成写入,任何访问这个字段的线程将会得到最新的值。

     2、在你写入前,会保证所有之前发生的事已经发生,并且任何更新过的数据值也是可见的,因为内存屏障会把之前的写入值都刷新到缓存。

 

看上去好像也没什么问题,但是问题就出在了增加变量这一步,中间的几步(从Load到Store)是不安全的,中间如果其他的CPU修改了值将会丢失

这就比如我们单例模式中懒汉式的问题,由于线程的速度是极快的,所以多个线程同时修改值这个问题,在volatile是没有解决的,也就是说volatile只保证了读取之前的数据可见和原子性和写入完成后的数据的可见和原子性,但在中间修改变量的环节,还是存在无法保证原子性的问题的。

 

说完了volatile,再来说说atomic,为什么atomic就可以保证原子性呢?它内部到底搞了什么鬼?

其实,是这样的:

CAS(比较并交换指令) ,这是atomic内部使用的技术,因为CAS是基于乐观锁的,也就是说当写入的时候,如果寄存器旧值已经不等于现值,说明有其他CPU在修改,那就继续尝试。所以这就保证了操作的原子性。

 

这里直接拿过来作者给出的解释,不过由于本人比较菜,对于这个CAS指令不太理解,不太清楚其他的cpu是怎么感知到寄存器中的值已经被修改了,希望有大神可以给解答一下。

 

                                                                      另外,附上原文地址:http://www.cnblogs.com/Mainz/p/3556430.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值