什么是CAS?
CAS是英文单词Compare And Swap的缩写,翻译过来就是比较并替换。
CAS机制当中使用了3个基本操作数:内存地址V,旧的预期值A,要修改的新值B。
更新一个变量的时候,只有当变量的预期值A和内存地址V当中的实际值相同时,才会将内存地址V对应的值修改为B。(通过自旋不断获取修改直至内存中的变量值与预期中的值一致才跳出)
相比较于synchronized采用悲观锁,默认并发严重,CAS采用一种乐观锁的属性,不断让线程进行尝试,适用于并发量比较小的情况。
CAS性能在并发量较小时较优的原因是少了锁队列的维护以及对上锁解锁等过程,但假如线程过多,频繁的尝试会导致性能较差。
CAS主要同于java.util.concurrent.atomic包中的类以及Lock中的底层实现。(synchronized在1.6版本前也用过CAS机制)
CAS的缺点:
1.CPU开销较大
在并发量比较高的情况下,如果许多线程反复尝试更新某一个变量,却又一直更新不成功,循环往复,会给CPU带来很大的压力。
2.不能保证代码块的原子性
CAS机制所保证的只是一个变量的原子性操作,而不能保证整个代码块的原子性。比如需要保证3个变量共同进行原子性的更新,就不得不使用Synchronized了。
3.ABA问题
这是CAS机制最大的问题所在。
1.A=>B 更新成功=>2.A=>B被阻塞更新失败=>3.B=>A更新成功=>2.A=>B更新成功
线程2属于多余操作,对同一操作进行二次执行,导致正常操作3被抵消。
例如你本来有100块钱,花了50块钱,后再存入50,此时余额应该是100,但由于步骤1的扣50执行了两次,因此余额只剩50.
为解决ABA问题,AtomicStampedReference类增加了版本号这一个判断条件,防止同一操作多次执行的错误。