并发编程中的 CAS 原理知道吗?
PassJava (佳必过) 项目全套学习教程连载中,关注公众号悟空聊架构第一时间获取。
文档在线地址: www.passjava.cn
原子整型类 AtomicInteger 的 getAndIncrement 方法就用到 CAS。
比如这一段代码:
atomicInteger.compareAndSet(10, 20);
调用 atomicInteger 的 CAS 方法,先比较当前变量 atomicInteger 的值是否是10,如果是,则将变量的值设置为20。
-
CAS 的全称:Compare-And-Swap(比较并交换)。比较变量的现在值与之前的值是否一致,若一致则替换,否则不替换。
-
CAS 的作用:原子性更新变量值,保证线程安全。
-
CAS 指令底层代码:需要有三个操作数,变量的当前值(V),旧的预期值(A),准备设置的新值(B)。
-
CAS 指令执行条件:当且仅当 V=A 时,处理器才会设置 V=B,否则不执行更新。
-
CAS 的返回值:V 的之前值。
-
CAS 处理过程:原子操作,执行期间不会被其他线程中断,线程安全。
-
CAS 并发原语:体现在 Java 语言中 sun.misc.Unsafe 类的各个方法。调用 UnSafe 类中的 CAS 方法,JVM 会帮我们实现出 CAS 汇编指令,这是一种完全依赖于硬件的功能,通过它实现了原子操作。由于 CAS 是一种系统原语,原语属于操作系统用于范畴,是由若干条指令组成,用于完成某个功能的一个过程,并且原语的执行必须是连续的,在执行过程中不允许被中断,所以 CAS 是一条 CPU 的原子指令,不会造成所谓的数据不一致的问题,所以 CAS 是线程安全的。
CAS 带来的问题:
1)频繁出现自旋,循环时间长,开销大(因为执行的是do while,如果比较不成功一直在循环,最差的情况,就是某个线程一直取到的值和预期值都不一样,这样就会无限循环)
2)只能保证一个共享变量的原子操作
-
当对一个共享变量执行操作时,我们可以通过循环CAS的方式来保证原子操作
-
但是对于多个共享变量操作时,循环CAS就无法保证操作的原子性,这个时候只能用锁来保证原子性。
作者简介:悟空,8年一线互联网开发和架构经验,用故事讲解分布式、架构设计、Java 核心技术。《JVM性能优化实战》专栏作者,开源了《Spring Cloud 实战 PassJava》项目,公众号:
悟空聊架构。
悟空的开源项目
https:///Jackson0714/PassJava-Platform
















