CAS的内存语义

一.首先介绍CAS的含义

  1. 使用CAS操作要两个变量,即预期值expect和更新值update都是 int类型的;
  2. JDK文档对该方法的说明如下:如果当前状态值等于预期值,则以原子方式将同步状态值设置为给定的更新值。此操作具有volatile读和写的内存语义;

二.从编译器和处理器的角度来分析CAS如何具有volatile读和写的内存语义

  1. 前面学过了volatile具有禁止指令重排序的作用,即:1)编译器不会对volatile读和volatile读后面的任意内存操作重排序;2)编译器不会对volatile写和volatile写前面的任意内存操作重排序。
  2. 组合上面两个条件,意味着为了同时实现volatile读和写的内存语义,编译器不会对CAS与CAS前面和后面的任意内存操作重排序。
  3. 从底层处理器的角度来看:程序会根据当前处理器的类型来决定是否对cmpxchg指令添加lock前缀。如果程序是在多处理器上运行的,就添加lock前缀(Lock Cmpxchg)。反之,如果程序是在单处理器上运行的,就省略lock前缀 (单处理器自身会维护单处理器内的顺序一致性,不需要lock前缀提供的内存屏障效果)。

三.lock前缀的指令的作用都是针对处理器而言的

  1. 确保对内存的读-改-写操作具有原子性。使用总线锁定(开销大)和缓存锁定的方式来保证执行的原子性,(这也是处理器保证原子性的原则)。缓存锁定大大降低lock前缀指令的执行开销。
  2. 禁止该指令,与指令之前和之后的读和写指令重排序。
  3. 把处理器的写缓冲区中的所有数据刷新到内存中。(保证可见性)

cas的原子操作是由cpu级别的锁来实现的,而他的这个可见性应该是对于多个cpu之间能够保证修改了变量的值对其他cpu是可见的。
而我们常说的Java并发中的内存可见性指的是JMM的可见性,所以cas对共享变量的修改对其他线程是不可见的。所以需要搭配volatile来修饰共享变量来保证线程间操作变量的原子性和可见性。

第2点和第3点所具有的内存屏障效果,足以同时实现volatile读和写的内存语义。

Volatile实现禁止指令重排优化,从而避免了多线程环境下程序出现乱序执行的现象。

首先了解一个概念,内存屏障(Memory Barrier)又称内存栅栏,是一个CPU指令,它的作用有两个:

  1. 保证特定操作的顺序
  2. 保证某些变量的内存可见性(利用该特性实现volatile的内存可见性)

内存屏障的作用即对应于lock前缀指令的第2点和第3点作用,所以就能解释CAS具有volatile读和写的功能。

内存屏障的详细作用可参考:
https://www.cnblogs.com/bbgs-xc/p/12731769.html#_label2

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值