比较并交换:通常指CompareAndSwap或CompareAndSet,乐观锁
1、CAS是一个原子操作,比较内存位置值且相等时修改内存位置值为新值,保证新值总基于最新信息计算,如其他线程期间修改这个值则CAS失败。CAS返回是否成功或者内存位置原来的值用于判断是否CAS成功。
2、JVM中的CAS操作是利用了处理器提供的CMPXCHG指令实现的。
优点:竞争不大时系统开销小
缺点:1)循环时间长开销大。2)ABA问题。3)只能保证一个共享变量原子操作。
一、AtomicInteger(原子性的更新和比较值)
1、自增方法 incrementAndGet:
CAS的自旋。无限循环:1)获取当前值。2)当前值+1 = 目标值。3)CAS操作,成功跳出,失败重复上述。
2、compareAndSet
一行代码。两个对象:
unsafe:直接接访问底层操作系统的“后门”,提供硬件级别原子操作:保证Compare和Swap之间原子性操作
valueOffset:AtomicInteger对象value成员变量在内存中的偏移量。value变量内存地址。unsafe.objectFieldOffset方法得到,
二、ABA
3个基本操作数:内存地址V(valueOffset),旧值A,新值B。
内存中有:值为A的变量,存在地址V中。三个线程想用CAS方式更新A:
1)线程1、2已获得当前值,3还未
2)1先一步成功,A更新为B;2被阻塞,没更新;3在1后,获得B。
3)3更新为A、2恢复,阻塞前已获A,compare检测,内存地址V中也是A,把A更新成B
例:100元存款,提50元,提款机出问题,同时提交两次,两个线程都是获取100元,要更新成50元。
理想情况下,一个成功,另一失败,扣一次。
2)1成功,100成50。2阻塞。这时,妈刚汇50。3成功,50改成100。
3)2恢复,已经获“当前值”100,compare检测,也是100,100更新成50。
解决办法:AtomicStampedReference用版本号做比较CAS机制:Compare操作。线程1获得值和地址V都是A,但版本号不相等,更新失败。
https://mp.weixin.qq.com/s/nRnQKhiSUrDKu3mz3vItWg
网友评论