CAS
353字约1分钟
2024-08-08
Java
并发机制实现原子操作有两种: 一种是锁,一种是 CAS
CAS
是 Compare And Swap
(比较并替换)的缩写
基本原理:CAS
有 3
个操作数,内存值V,旧的预期值 A
,要修改的新值 B
。当且仅当预期值 A
和内存值 V
相同时,将内存值 V
修改为 B
,否则什么都不做
public static void main(String[] args) {
AtomicInteger atomicInteger = new AtomicInteger(2020);
// 期望、更新
// public final boolean compareAndSet(int expect, int update)
// 如果我期望的值达到了,那么就更新,否则不更新,CAS 是 CPU 的并发原语
atomicInteger.compareAndSet(2020, 2021);
System.out.println(atomicInteger.get());
// false
System.out.println(atomicInteger.compareAndSet(2020, 2021));
// 2021
System.out.println(atomicInteger.get());
}
缺点
循环会耗时
一次性只能保证一个共享变量的原子性
ABA
问题
ABA
问题
旧预期值被其他线程从 A -> B
,再 B -> A
,另外个线程的旧预期值是 A
原子引用
带版本号的原子操作可以解决 ABA
问题,对应的 思想:乐观锁
public static void main(String[] args) {
// initialRef 原始值,initialStamp 版本号
AtomicStampedReference<Integer> atomicStampedReference = new AtomicStampedReference(1, 2);
// 获得版本号
atomicStampedReference.getStamp();
// 旧的预期值、新的值、旧版本号、新版本号
atomicStampedReference.compareAndSet(1, 2,
atomicStampedReference.getStamp(), atomicStampedReference.getStamp() + 1);
}
上述代码有个坑,因为使用的 Integer
,如果超过了 -128 ~ 127
这个范围,他会修改失败,因为值的比较是用的 ==