为什么AtomicInteger 还有compareAndSet()?
在ribbon的轮询负载均衡就是用了AtomicInteger的compareAndSet()来实现无锁

  1. class SimulatedCAS{
  2. volatile int count;
  3. // 实现count+=1
  4. addOne(){
  5. do {
  6. newValue = count+1; //①
  7. }while(count !=
  8. cas(count,newValue) //②
  9. }
  10. // 模拟实现CAS,仅用来帮助理解
  11. synchronized int cas(
  12. int expect, int newValue){
  13. // 读目前count的值
  14. int curValue = count;
  15. // 比较目前count值是否==期望值
  16. if(curValue == expect){
  17. // 如果是,则更新count的值
  18. count= newValue;
  19. }
  20. // 返回写入前的值
  21. return curValue;
  22. }
  23. }

CAS 缺点

1、ABA问题。CAS比较交换时,是检查当前值与期望值是否一致。试想一下,如果某个值由A变成了B,再由B变回了A,那么在做CAS比较时,会认为值没有变化,但实际是发生了变化。ABA问题的解决思路是给数据加一个版本号,每次更新后对其版本加1,这样在值变回A之后,其版本已不是原来的版本了
2、开销大。在高并发情况下,自旋CAS如果长时间不成功,会一直执行循环操作,给CPU带来非常大的执行开销。所以其适用于那些并发不是很大的场景。
21 | 原子类:无锁工具类的典范 - 图1

课后思考

cas的获取值 要放在循环体内