为什么AtomicInteger 还有compareAndSet()?
在ribbon的轮询负载均衡就是用了AtomicInteger的compareAndSet()来实现无锁
class SimulatedCAS{
volatile int count;
// 实现count+=1
addOne(){
do {
newValue = count+1; //①
}while(count !=
cas(count,newValue) //②
}
// 模拟实现CAS,仅用来帮助理解
synchronized int cas(
int expect, int newValue){
// 读目前count的值
int curValue = count;
// 比较目前count值是否==期望值
if(curValue == expect){
// 如果是,则更新count的值
count= newValue;
}
// 返回写入前的值
return curValue;
}
}
CAS 缺点
1、ABA问题。CAS比较交换时,是检查当前值与期望值是否一致。试想一下,如果某个值由A变成了B,再由B变回了A,那么在做CAS比较时,会认为值没有变化,但实际是发生了变化。ABA问题的解决思路是给数据加一个版本号,每次更新后对其版本加1,这样在值变回A之后,其版本已不是原来的版本了
2、开销大。在高并发情况下,自旋CAS如果长时间不成功,会一直执行循环操作,给CPU带来非常大的执行开销。所以其适用于那些并发不是很大的场景。
课后思考
cas的获取值 要放在循环体内