目录
1、CAS的原理
CAS 即 compare and swap(比较与交换)
,是一种乐观锁机制,也叫无锁机制。即不使用锁的情况下实现多线程之间的变量同步,也就是在没有线程被阻塞的情况下实现变量的同步,所以也叫非阻塞同步(Non-blocking Synchronization)
CAS 中涉及三个要素:
-
需要读写的内存值 V
-
进行比较的值 A
-
拟写入的新值 B
当且仅当预期值A和内存值V相同时,将内存值V修改为B,否则什么都不做
CAS的原子性
CAS操作是原子的,这意味着它要么完全执行成功,要么完全不执行。即使在多线程环境中,也不会有其他线程能够干扰CAS操作的执行
在之前文章Java并发—volatile关键字的作用及使用场景-CSDN博客中使用了volatile关键字修改变量x的过程,但修改和写回操作不是原子性,还是会有数据不一致性的问题,CAS就可以解决这个问题,那使用CAS操作来修改共享变量x,流程又会是如何呢?
还是使用之前的案例:🌰线程A和线程B从主内存读取和修改x=1的过程
步骤:
1.初始化:x=1,存储在主内存
2.线程A读取:A从主内存读取,复制x=1到A的工作内存
3.线程B读取:B从主内存读取x,复制x=1到B的工作内存
4.线程A修改:A在工作内存中修改x=2
5.线程A尝试CAS写回:A将工作内存中的x=2与主内存中的x=1进行比较
如果主内存中仍然是x=1(预期值),则CAS操作成功,x=1更新至x=2
如果主内存中x≠1(被其他线程修改),则CAS操作失败,线程A需要重新读取更新的值并再次尝试重新读取最新的值
6.线程B修改:B在工作内存中修改x=3
7.线程B尝试CAS写回
如果主内存中x=1(这是B读取时的值,但此时可能已经被A修改x=2),也就是线程B以为主内存中是x=1(预期值),但实际上主内存是x=2(实际值),预期值与实际值不符,则 CAS操作失败
B需要重新读取最新的值x=2,并尝试CAS操作
8.线程B重新读取:x=2
9.线程B再次尝试CAS写回:B再次尝试将x=2更新至x=3,如果此时没有其他线程修改x,则CAS操作成功
由上述流程可以看出当使用CAS操作来修改共享变量x时,与volatile修改共享变量x流程会有所不同,CAS也成功得解决了上一篇文章中遗留问题
2、CAS的问题
看起来好像又没问题了,但CAS会出现ABA问题
1)ABA问题
❓什么是ABA问题呢?
ABA 问题说的是,如果一个变量第一次读取的值是 A,准备好需要对 A 进行写操作的时候,发现值还是 A,那么这种情况下,能认为 A 的值没有被改变过吗?可以是由 A -> B -> A 的这种情况
❓那如何解决呢?
为了解决ABA问题,常见的做法是在CAS操作中加入版本号或标记。例如,可以使用 AtomicStampe