1.什么是CAS?
CAS(Compare And Swap):比较并交换。它是一条CPU指令,可以在不加锁的情况下,原子性地完成比较和交换操作。
CAS有3个操作数:
- 需要读写的内存值:V
- 旧的预期值:A
- 更新值:B
具体操作流程如下:
当且仅当V(内存中)的值等于A(预期值)时,CAS才通过原子方式用B(新的值)来更新V的值,否则不执行更新。
2.CAS的执行过程
你也许要问:为什么还需要设计一个预期值A和V进行比较,而不直接交换V和B呢?
因为这样才可以在并发环境下完成正确的操作,我们想象一下这个场景:
线程1和线程2想共同完成对变量n的自增操作,它们的目标是将n从1加到100,但是我们知道n++
或者++n
都是线程不安全的,这时CAS就有了用武之地。
(1)初始时刻,我们设置n初始为1,那么预期值A也为1,因为是自增操作,所以更新值B设置为A+1.
(2)假设线程1先进行CAS的自增操作,发现预期值A
和内存值V
相等,所以用B
来更新V的值。如下:
(3)接着线程2进行CAS操作,却发现V为2,A为1,A和V不相等
,所以不能更新,而是进入一个循环来重新获取V的值赋值给A。
(4)线程2接下来进行第二次CAS操作,发现A和V相等
,则更新V为3。如下:
(5)接着又轮到线程1,它先发现不能更新,接着将当前内存值赋值给A,A和V相等后继续完成自增操作。循环往复。
至此两个线程并发自增n就实现了,这一过程既不用加锁,也能实现并发安全。
3.CAS的缺陷
(1)ABA问题
并发环境下,假设初始条件是A,当一个线程再次修改时,发现还是A,修改成功;但是在此之前它可能先被修改为B,又被修改回了A,对此我们不得而知。
(2)循环时间开销大
当一个线程更新不成功,该线程会进入自旋状态,它会不断地尝试,如果长时间不能更新成功,就会给CPU带来很大的开销。
(3)只能保证一个变量的原子操作
CAS 保证的是对一个变量执行操作的原子性,如果对多个变量操作时,CAS 目前无法直接保证操作的原子性的。