CAS(CompareAndSwap)底层原理

Posted bomdeyada

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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

 

 

 

 

 

以上是关于CAS(CompareAndSwap)底层原理的主要内容,如果未能解决你的问题,请参考以下文章

06 CAS的原理和AQS

ReentrantLock实现原理

CompareAndSwap原子操作原理

Java synchronized实现原理深度剖析

从CAS算法底层开始的关于计算机数据存储及处理的浅显梳理

CAS的实现原理