CAS概念
CAS(Compare and Swap)是一种多线程编程中常用的原子操作,它可以在多线程并发访问的情况下,保证数据的完整性和一致性。CAS的主要操作包括比较和替换,它会先比较内存中的某个位置的值是否等于预期值,如果是,则将该位置的值替换为新值;否则,什么都不做。这种操作可以确保在多线程并发访问的情况下,不会出现数据竞争和数据不一致的情况。
主要是通过处理器的指令来保证操作的原子性,它包含三个操作数:
- 变量内存地址,V表示
- 旧的预期值,A表示
- 准备设置的新值,B表示
当执行CAS指令时,只有当V等于A时,才会用B去更新V的值,否则就不会执行更新操作。
CAS缺点
ABA问题:ABA的问题指的是在CAS更新的过程中,当读取到的值是A,然后准备赋值的时候仍然是A,但是实际上有可能A的值被改成了B,然后又被改回了A,这个CAS更新的漏洞就叫做ABA。只是ABA的问题大部分场景下都不影响并发的最终效果。
Java中有AtomicStampedReference来解决这个问题,他加入了预期标志和更新后标志两个字段,更新时不光检查值,还要检查当前的标志是否等于预期标志,全部相等的话才会更新。(即类似检查版本)
循环时间长开销大:自旋CAS的方式如果长时间不成功,会给CPU带来很大的开销。
只能保证一个共享变量的原子操作:只对一个共享变量操作可以保证原子性,但是多个则不行,多个可以通过AtomicReference来处理或者使用锁synchronized实现
CAS自旋锁
CAS自旋锁的实现是基于比较交换算法实现,通过修改共享区域的值直到修改成功为止。
CAS自旋锁demo
import java.util.concurrent.atomic.AtomicInteger;
public class SpinLock {
//AtomicInteger线程安全
private AtomicInteger state = new AtomicInteger(0);
public void lock() {
//若无占用(为0)则占用锁(0->1),若占用则自旋等待
while (!state.compareAndSet(0, 1)) {
//自旋
System.out.println("自旋等待");
}
//占用成功,处理逻辑代码
//unlock();
}
public void unlock() {
state.set(0);
}
}
可以参考这位博主写的 (多线程)CAS ,我这边是比较简单的介绍。