Java CAS简析

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java CAS简析相关的知识,希望对你有一定的参考价值。

什么是CAS

CAS:Compare and Swap,它是一种原子操作,什么是原子操作,可以在多线程编程中实现数据交换而不被打断。是用来更新变量的,当多个线程使用CAS来更新变量时,只有一个线程可以更新变量的值,其他线程都会失败,失败的线程不回被挂起,而是重试直到成功为止。

CAS实现方式,有三个变量,内存值V,处理器缓存(预期值)A,更新值B。比较内存值与预期值,相等则说明没有其他线程操作共享数据,则更新内存值为B;不等说明共享数据V已经被其他线程改动了,放弃更新操作,重新load共享数据,重试之前操作。

CAS的运用

乐观锁:其实现机制是基于CAS的,每次不加锁,假设没有冲突完成操作,如果有冲突,充实知道成功为止。

Java原子类:AtomicInteger等

源码分析

一起看一下AtomicInteger是怎么实现free-lock的。

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;
 public final int incrementAndGet() {
        return unsafe.getAndAddInt(this, valueOffset, 1) + 1;
    }

value 是用volatile 修饰的,可以保证get与set的原子性,但无法保证incrementAndGet读写改的复合操作。其实际调用的方法是unsafe的getAndAddInt

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 通过JNI调用C++ 的一些方法,首先是根据内存地址获取到value的值,然后调用compareAndSwapInt,true:更新变量成功,false:不成功。compareAndSwapInt经过汇编后最主要的是CMPXCHG指令,该指令是 操作系统级别的原子操作。所以,抛开C++与汇编源码,可以理解为Java运用了os的原子性来实现无锁编程。

那操作系统是如何保证CAS原子性呢?在写操作前会有一个Lock前缀,它会引发两件事情。

  1. 将当前处理器缓存行的数据写回到内存行。
  2. 这个写缓存操作会使其他CPU里的缓存了该内存地址的数据无效。
使用总线锁保证原子性:

处理器提供一个Lock# 信号,当处理器在总线上输出此信号时,其他处理的请求将被阻塞,改处理器就可以独占共享内存。

缺点:对于多核(32,64),其中一个cpu锁住了总线,其他所有核与内存之间的通信都被锁住了,开销太大。

使用缓存锁保证原子性

直接修改内存,缓存一致性机制来保障操作的原子性。

ABA 问题

一个值原来是A,变成了B,又变成了A,那么使用CAS进行检查时会发现它的值没有变化,其实却变化了,解决思路是加上版本号。

参考:

  1. Java 并发编程的艺术
  2. 用AtomicStampedReference解决ABA问题
  3. 非阻塞同步算法与CAS(Compare and Swap)无锁算法

以上是关于Java CAS简析的主要内容,如果未能解决你的问题,请参考以下文章

cas简析

cas简析

markdown [Apereo CAS 3.5 CORE] Apereo CAS 3.5 #CAS的核心代码片段

Python中的基本函数及其常用用法简析

javaCompiler简析

RPC高性能框架总结3.NIO示例代码编写和简析