CAS
Posted mengchunchen
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了CAS相关的知识,希望对你有一定的参考价值。
CAS,在Java并发应用中通常指CompareAndSwap,即比较并交换。
CAS是一个原子操作,它比较一个内存位置的值并且只有相等时修改这个内存位置的值为新的值,保证了新的值总是基于最新的信息计算的,如果有其他线程在这期间修改了这个值则CAS失败。
synchronized属于重量级锁,很多时候会引起性能问题。
volatile是轻量级锁,但是volatile不能保证原子性。
像synchronized这种独占锁属于悲观锁,它是在假设一定会发生冲突的,那么加锁恰好有用。
除此之外,还有乐观锁,乐观锁的含义就是假设没有发生冲突,那么我正好可以进行某项操作,如果要是发生冲突呢,那我就重试直到成功。
乐观锁最常见的就是CAS。 我们在读Concurrent包下的类的源码时,发现无论是ReenterLock内部的AQS,还是各种Atomic开头的原子类,内部都应用到了CAS。
1 public class Test { 2 3 public AtomicInteger i; 4 5 public void add() { 6 i.getAndIncrement(); 7 } 8 } 9 10 public final int getAndIncrement() { 11 return unsafe.getAndAddInt(this, valueOffset, 1); 12 } 13 14 public final int getAndAddInt(Object var1, long var2, int var4) { 15 int var5; 16 do { 17 var5 = this.getIntVolatile(var1, var2); 18 } while(!this.compareAndSwapInt(var1, var2, var5, var5 + var4)); 19 20 return var5; 21 }
var5 = this.getIntVolatile(var1, var2);
var2是在内存中的偏移地址,通过这个地址拿到对象var1在内存中的值,赋给var5
然后比较var5是否跟对象var1在内存中的值相等,如果相等,则将这个值更新,如果不相等,则重试。
CAS是在JNI
里是借助于一个CPU
指令完成的,所以还是原子操作。
CAS的缺点:
ABA问题:
CAS需要在操作值的时候检查下值有没有发生变化,如果没有发生变化则更新,但是如果一个值原来是A,变成了B,又变成了A,那么使用CAS进行检查时会发现它的值没有发生变化,但是实际上却变化了。这就是CAS的ABA问题。
常见的解决思路是使用版本号。在变量前面追加上版本号,每次变量更新的时候把版本号加一,那么A-B-A
就会变成1A-2B-3A
。
目前在JDK的atomic包里提供了一个类AtomicStampedReference
来解决ABA问题。
这个类的compareAndSet方法作用是首先检查当前引用是否等于预期引用,并且当前标志是否等于预期标志,如果全部相等,则以原子方式将该引用和该标志的值设置为给定的更新值。
以上是关于CAS的主要内容,如果未能解决你的问题,请参考以下文章