CAS(Compare-And-Set)原子操作

CAS

原子性

一组操作不允许被其他线程打断被称为原子性。
synchronized关键字可以实现原子性,只要拿到锁才会进入synchronized,被synchronized关键字引用的语句不会被其他线程打断,
那么为什么有了synchronized关键字还要搞个CAS,这就有点多次一举了。原因是我们的一些简单操作,例如自增这种操作本来只需要一两条指令,加上synchronized关键字后里面变成十多条指令,这样会使执行效率下降。CAS底层使用CPU的CMPXCHG指令来判断当前值是否与期望值相等,这样就省去了synchronized的十多条指令。

CAS的执行逻辑

CAS会比较内存中的值与期望值是否相等,如果相等,那么将新值写入到变量中,如果不相等,那么舍弃写入,这样做可以保证写入的值与我们希望的值一致,
CAS逻辑操作一遍有三个值,分别是期望值,比较值和写入的值。CAS源码如下所示
可以根据第一个参数和第二个参数可以找到内存中的值也就是比较的值,第三个参数是期望值,第四个参数是写入的值。
image
CAS执行不会相synchronized一样阻塞,CAS在执行的过程中如果发现与期望值不符会进行回滚。如果想要保证值一定写入成功,那么就需要加while循环来校验值是否写入成功了,如下图所示:
image
由于CAS不会阻塞,所有执行效率会很高。
image

CAS原子操作的弊端

ABA问题

线程1读取变量值A,看到变量值为1
线程2读取到变量值A,看到变量值为1,改为2,经过一系列业务操作又将变量值改为1
线程1比较期望值与内存值都为1,CAS执行成功。
但是上面执行过程中是有问题的,由于变量1发生了修改,打破了原子性,这时候CAS是不应该执行成功的,但是却执行成功了。
解决方案就是加版本号,每次修改变量值时版本号加1,在执行CAS操作提交时,判断值+版本号是否一致,如果一致才允许提交。

循环时间长,开销大

CAS在执行过程中如果执行失败会while循环直到执行成功。

CAS只能保证单个变量的原子性

CAS只能对单个变量进行原子操作,如果是同时操作多个变量的话那么就无法保证原子性了。其实可以将多个变量封装成一个对象来保证原子性。

posted @ 2025-09-06 08:25  RainbowMagic  阅读(37)  评论(0)    收藏  举报