zoukankan      html  css  js  c++  java
  • CAS(CompareAndSwap)底层原理

    CAS:Compare and Swap,即比较再交换。

    在对compareAndSwapObject追源码的过程中,出现 "Source not found"的情况,查了一下,原来是该方法并非由JAVA书写开发,而是引入的其他语言。

    jdk5增加了并发包java.util.concurrent.*,其下面的类使用CAS算法实现了区别于synchronouse同步锁的一种乐观锁。JDK 5之前Java语言是靠synchronized关键字保证同步的,这是一种独占锁,也是是悲观锁,从而形成了在安全、效率的中新的思路,

    casNext(Node<E> cmp, Node<E> val) {

      return UNSAFE.compareAndSwapObject(this, nextOffset, cmp, val);
    }

    UNSAFE_ENTRY(jboolean, Unsafe_CompareAndSwapObject(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jobject e_h, jobject x_h))
      UnsafeWrapper("Unsafe_CompareAndSwapObject");
      oop x = JNIHandles::resolve(x_h); // 新值
      oop e = JNIHandles::resolve(e_h); // 预期值
      oop p = JNIHandles::resolve(obj);
      HeapWord* addr = (HeapWord *)index_oop_from_field_offset_long(p, offset);// 在内存中的具体位置
      oop res = oopDesc::atomic_compare_exchange_oop(x, addr, e, true);// 调用了另一个方法
      jboolean success  = (res == e);  // 如果返回的res等于e,则判定满足compare条件(说明res应该为内存中的当前值),但实际上会有ABA的问题
      if (success) // success为true时,说明此时已经交换成功(调用的是最底层的cmpxchg指令)
        update_barrier_set((void*)addr, x); // 每次Reference类型数据写操作时,都会产生一个Write Barrier暂时中断操作,配合垃圾收集器
      return success;
    UNSAFE_END
    

     

    CAS是一种无锁、比较交换算法,修改的方法包含三个核心参数(V,E,N) V:要更新的变量、E:预期值、N:新值。在无锁多线程的情况下,多个线程同时取得 V:要更新的变量、E:预期值,

    通过算法获得其内存地址,同时竞争CPU的时间片,只有某个线程优先拿到执行权时,才对当前持有的内存地址与原有地址进行比较,

    只有当V==EV=N否则表示内容已经被更新过,则取消当前操作。

     CAS比较与交换的伪代码可以表示为:

     do{

      备份旧数据;

      基于旧数据构造新数据;

     }while(!CAS( 内存地址,备份的旧数据,新数据 ))

      

    而cpu层面的CAS,介绍如下:

    Compares the value in the AL, AX, or EAX register (depending on the size of the operand) with the first operand (destination operand). If the two values are equal, the second operand (source operand) is loaded into the destination operand. Otherwise, the destination operand is loaded into the AL, AX, or EAX register.

    (若期望值等于对象地址存储的值,则用新值来替换对象地址存储的值,否则,把期望值变为当前对象地址存储的值)

    This instruction can be used with a LOCK prefix to allow the instruction to be executed atomi-cally. To simplify the interface to the processor’s bus, the destination operand receives a write cycle without regard to the result of the comparison. The destination operand is written back if the comparison fails; otherwise, the source operand is written into the destination. (The processor never produces a locked read without also producing a locked write.)

    CAS是所有原子变量的原子性的基础,为什么一个看起来如此不自然的操作却如此重要呢?其原因就在于这个native操作会最终演化为一条CPU指令cmpxchg,而不是多条CPU指令。由于CAS仅仅是一条指令,因此它不会被多线程的调度所打断,所以能够保证CAS操作是一个原子操作。补充一点,当代的很多CPU种类都支持cmpxchg操作,但不是所有CPU都支持,对于不支持的CPU,会自动加锁来保证其操作不会被打断。
    由此可知,原子变量提供的原子性来自CAS操作,CAS来自Unsafe,然后由CPU的cmpxchg指令来保证。

     参考:https://blog.csdn.net/qqqqq1993qqqqq/article/details/75211993

        https://www.jianshu.com/p/ab2c8fce878b

  • 相关阅读:
    洛谷P4175 网络管理
    洛谷P2605 基站选址
    洛谷P3723 礼物
    bzoj3771 Triple
    洛谷P3321 序列统计
    bzoj2194 快速傅里叶之二
    1109课堂内容整理
    响应式网页
    表单隐藏域有什么作用?
    1106课堂笔记
  • 原文地址:https://www.cnblogs.com/bomdeyada/p/13231387.html
Copyright © 2011-2022 走看看