美文网首页Java篇
原子操作CAS

原子操作CAS

作者: w达不溜w | 来源:发表于2022-02-23 22:30 被阅读0次

    原子操作CAS

    1、CAS的基本原理

    利用了现代处理器都支持的CAS的指令,循环这个指令,直到成功为止

    CAS(Compare And Swap),指令级别保证了这是一个原子操作(指操作不会被线程调度机制打断)

    它有3个操作数:内存值V,预期值A,更新值B,如果内存值V和期望值A相等,就把V修改为B,循环CAS操作,直到成功为止。


    cas自旋.png

    以AtomicInteger为例:

    //++i
    public final int incrementAndGet() {
      return U.getAndAddInt(this, VALUE, 1) + 1;
    }
    //i++
    public final int getAndIncrement() {
      return U.getAndAddInt(this, VALUE, 1);
    }
    //额外提供了compareAndSet方法,第一个期望值,第二个希望修改成的值
    public final boolean compareAndSet(int expect, int update) {
      return U.compareAndSwapInt(this, VALUE, expect, update);
    }
    
    //Unsafe类
    public final int getAndAddInt(Object var1, long var2, int var4) {
      int var5;
      do {
        var5 = this.getIntVolatile(var1, var2);
        ////compareAndSwapInt是一个native方法,CPU原语指令,是连续执行不会被打断的,所以可以保证原子性。
      } while(!this.compareAndSwapInt(var1, var2, var5, var5 + var4));
      return var5;
    }
    

    AtomicInteger由硬件提供原子操作指令实现的。在非激烈竞争的情况下,开销更小,速度更快。

    public static void main(String[] args) {
      AtomicInteger atomicInteger = new AtomicInteger(6);
      //true
      System.out.println(atomicInteger.compareAndSet(6,66));
      //false
      System.out.println(atomicInteger.compareAndSet(6,66));
    }
    

    AtomicInteger的compareAndSet方法就是CAS操作:

    初始值6,调用 compareAndSet(6,66),期望值为6(相等),主内存中的值被修改为66,输出true;

    第2次调用 compareAndSet(6,66),期望值为6,但此时主内存中的值为66,输出false。

    2、CAS的问题
    • ABA问题

      变量A,修改为变量B,然后又修改为A,实际上已经修改过了。

      对于这个问题,每次修改加上类似版本戳的方式,JDK提供了:

      AtomicMarkableReference:是否修改过

      AtomicStampedReference:改过几次

    • 开销问题

      自旋CAS不成功,就会一直循环执行,直到成功,如果长时间不成功,会给CPU带来大的执行开销。

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

      这个问题可以采用合并共享变量的方式处理,JDK提供了AtomicReference类来保证引用对象之间的原子性,就可以把多个变量放在一个对象里来进行CAS操作

    相关文章

      网友评论

        本文标题:原子操作CAS

        本文链接:https://www.haomeiwen.com/subject/roualrtx.html