CAS
2021-04-23 19:32:14 15 举报
AI智能生成
CAS运行机制及存在的问题
作者其他创作
大纲/内容
是什么?
CAS其实就是Compare And Swap 的简写,它是一条 CPU 并发原语。原语的执行必须是连续的,在执行过程中不允许中断,也就是说CAS是一条原子指令,不会造成所谓的数据不一致的问题。
源码
Unsafe类是 Java 中用于直接操作内存数据的一个类(类似于C语言中的指针操作),其中包含很多的本地方法(native)。
public final native boolean compareAndSwapInt(Object var1, long var2, int var4, int var5);
Object var1:代表当前对象
long var2:代表内存偏移量,相当于对象值的引用地址
int var4:代表期望值,使用期望值和当前对象中的值进行比较
int var5:代表要交换的值
使用案例
public final int getAndAddInt(Object var1, long var2, int var4) {
int var5;
do {
var5 = this.getIntVolatile(var1, var2);
} while(!this.compareAndSwapInt(var1, var2, var5, var5 + var4));
return var5;
}
int var5;
do {
var5 = this.getIntVolatile(var1, var2);
} while(!this.compareAndSwapInt(var1, var2, var5, var5 + var4));
return var5;
}
当前对象
该变量值在内存中的偏移地址
需要增加的值大小
优点
避免加互斥锁
提高程序运行效率
缺点
ABA问题
使用 CAS 会产生 ABA 问题,这是因为 CAS 算法是在某一时刻取出内存值然后在当前的时刻进行比较,中间存在一个时间差,在这个时间差里就可能会产生 ABA 问题
ABA 问题的过程是当有两个线程 T1 和 T2 从内存中获取到值A,线程 T2 通过某些操作把内存 值修改为B,然后又经过某些操作将值修改为回值A,T2退出。线程 T1 进行操作的时候 ,使用预期值同内存中的值比较,此时均为A,修改成功退出。但是此时的A以及不是原先的A了,这就是 ABA 问题
解决方式
添加版本号
AtomicStampedReference
自旋时间过长
由于单次 CAS 不一定能执行成功,所以 CAS 往往是配合着循环来实现的,有的时候甚至是死循环,不停地进行重试,直到线程竞争不激烈的时候,才能修改成功。
应用场景本身就是高并发的场景,就有可能导致 CAS 一直都操作不成功,这样的话,循环时间就会越来越长。而且在此期间,CPU 资源也是一直在被消耗的,这会对性能产生很大的影响。所以这就要求我们,要根据实际情况来选择是否使用 CAS,在高并发的场景下,通常 CAS 的效率是不高的
解决方式:并发不算太高的时候选择CAS,本身乐观锁就是假设冲突不多
线程安全的范围不能灵活控制
CAS操作的是单个对象,不能同时保证多个对象的原子性
解决方案:利用一个新的类,来整合刚才这一组共享变量,这个新的类中的多个成员变量就是刚才的那多个共享变量,然后再利用 atomic 包中的 AtomicReference 来把这个新对象整体进行 CAS 操作,这样就可以保证线程安全。
0 条评论
下一页