CAS

悲观锁与乐观锁

  • 悲观锁:

我们常说的锁,我们任务访问临界资源总是会发生冲突,所以访问临界资源前要获取到锁,以保证只有一个线程可以访问临界资源。

  • 乐观锁:

乐观锁又称无锁,它假设共享资源很少发生冲突,线程不断的执行。发生冲突时使用 CAS 技术来保证线程安全性。

乐观锁 没有使用锁,所以不会发生死锁。但会不断执行线程,产生自旋,消耗CPU资源。

CAS 概念

CAS 全称 Compare And Swap,意为比较并且交换,这时一个原子行为,只有相等的时候才会赋值成功。

当多个线程同时进行CAS操作时,只有一个成功,其他线程返回失败,其他线程可以继续重试,也可以放弃。

CAS 原理

  • CAS 是一个原子操作,Java 如何实现的呢?

Java 中有一个 Unsafe 类,里面有关于 CAS 的native方法。native 方法由 底层的 JVM 使用 C 或 C++ 实现,CAS 实现依赖于 操作系统和CPU,例如 X86 平台依赖于 cmpxchgl指令实现 CAS 操作。


    public final native boolean compareAndSwapObject(Object var1, long var2, Object var4, Object var5);

    public final native boolean compareAndSwapInt(Object var1, long var2, int var4, int var5);

    public final native boolean compareAndSwapLong(Object var1, long var2, long var4, long var6);

原子操作 AtomicInteger

JDK 提供了用于原子操作的类,位于 java.util.concurrent.atomic

我们以 AtomicInteger类为例,看看 Java 如何实现原子操作的。

来看 getAndAdd

    public final int getAndAdd(int delta) {
        return unsafe.getAndAddInt(this, valueOffset, delta);
    }

unsafe 底层实现,采用 do-while 循环。保证原子操作。

    public final int getAndAddInt(Object var1, long var2, int var4) {
        int var5;
        do {
            var5 = this.getIntVolatile(var1, var2);
        } while(!this.compareAndSwapInt(var1, var2, var5, var5 + var4));

        return var5;
    }

unsafe是初始化静态变量 , valueOffset 是内部 value 字段偏移量。

    private static final Unsafe unsafe = Unsafe.getUnsafe();
    private static final long valueOffset;

    static {
        try {
            valueOffset = unsafe.objectFieldOffset
                (AtomicInteger.class.getDeclaredField("value"));
        } catch (Exception ex) { throw new Error(ex); }
    }

    private volatile int value;
    

CAS 原子操作的三大问题

ABA 问题

所谓 ABA 问题,就是一个值原来为 A,更新成了 B,然后又更新为 A。这个时候使用 CAS 时检测不出变化的,实际上数据变化了2次。

解决方法是在变量前面加上版本号或者时间戳

Java 提供了 AtomicStampedReference来解决 ABA 问题。

循环时间长开销大

  • JVM 底层优化,例如支持 处理器的 pause 指令。
  • 锁升级,达到一定条件后,停止 CAS 操作。

只能保证一个共享变量的原子操作

  • 使用锁,保证只有一个线程可以操作
  • 使用 AtomicReference 类保证对象间的原子性,把多个对象放到一个对象里进行 CA 操作。
Last Updated:
Contributors: himcs