CAS分析
一、概念
CAS英文名为 Compare And Swap 中文意思为比较并交换
CAS机制中使用了3个基本操作数,内存地址V,旧的预期值A,要修改的新值B,更新一个变量的时候,只有当预期值A等于内存地址V中的实际值时,才能将内存地址V对应的值改位B
举例:在内存地址V中,存储着值为10的变量,此时,线程1想要对变量值加1,对线程1来说预期值为10,更新值为11,若在线程1要提交更新之前,线程2抢先修改了内存地址中的值,线程1开始提交更新,发现内存地址中的值为11,而自己预期值为10,不相等提交失败,然后线程1通过自旋重新获取内存地址中的值,重新计算需要更新的值,此时,对线程1来说,A=11,B=12。
从思想上来说,CAS属于乐观锁,
二、CAS缺点
CPU开销较大
- 在并发量比较高的情况下,如果许多线程通过自旋反复尝试更新某一个变量,却一直又更新不成功,会给CPU带来极大的压力
不能保证代码块的原子性
- CAS机制所保证的只是一个变量的原子性操作,而不能保证整个代码块的原子性,比如需要保证3个变量共同进行原子性的更新,就不得不使用重量级的 Synchronized 或者相应的lock
- ABA问题
三、CAS带来的ABA问题以及解决方案
- ABA问题产生场景
假如内存地址中有一个值为A的变量,现在有三个线程想要更新内存地址中的值,
线程1:获取当前值A,期望更新为B,
线程2:获取当前值A,期望更新为B,
线程3:期望更新为A
接下来,线程1抢先一步执行成功,把当前值从A更新为B,同时线程2因为某种原因被阻塞了,没有进行更新操作,线程3此时过来获取到内存地址中值B,将B改为A,最后线程2恢复了运行状态,发现此时内存地址中的值和自己的期望值相等,又将值改为B。此时内存中的地址值经历了 A —> B —> A的改变。
表面上看没有什么问题,但是在某些场景下就是致命的。
比如,小明网上账户上有100块钱,要支付50元,由于网络等原因,多点了几下,第一次将账户的余额改为50元,此时,小红给小明转账50元,此时账户余额为100元,由于上面的网络延迟,多点几下的操作请求也遵循CAS,期望值100,更新值50,又将小明的账户余额改为50元,此时小明实际余额少了50元。
解决方案:
添加一个版本号,每次比较并更新版本号就能解决ABA问题。
