深入理解CAS

概念

CAS,也就是compare and swap,比较并交换,是一条CPU并发原语,实现并发算法时常常用到的一种锁机制。它是区别于synchronized同步锁的一种乐观锁。synchronized关键字保证同步时是独占资源的,是悲观锁。

原理

CAS是一种无锁算法,CAS有3个操作数,内存值V,旧的预期值A,要修改的新值B。当且仅当预期值A和内存值V相同时,将内存值V修改为B,否则什么都不做。

CAS并发原语体现在Java语言中就是Unsafe类中的各个方法。调用Unsafe类中的CAS方法,JVM会实现中CAS汇编指令。这是一项完全依赖于硬件的功能,通过他实现了原子操作。在此需要理解原语的概念,原语是由若干指令组成用于完成某个功能的一个过程,并且原语的执行必须是连续的,在执行过程中不允许被中断。也就是说CAS不会造成所谓的数据不一致的问题。

  1. Unsafe。是CAS的核心类,由于Java方法无法直接访问底层系统,需要通过本地(native)方法来访问,Unsafe相当于一个后门,基于该类可以直接操作特定内存的数据。Unsafe类存在于sun.misc包中,其内部方法操作可以像C指针一样直接操作内存。
  2. 保证原子性的atmicInteger中的getAndIncrement方法中使用了Unsafe的getAndAddInt方法,包含三个参数,this指当前操作对象,valueOffset表示该变量值在内存中的偏移地址,因为Unsafe就是根据内存偏移地址去获取数据的,最后一个参数是增加值,固定为1。
  3. 在compareAndSwapInt方法中,var1就是AtomicInteger对象本身,var2是该对象值的引用地址,var4是指需要变动的数量,而var5指的是用var1、var2找出的主内存中真实的值。用该对象当前的值与var5(也就是预期值)比较,如果相同,则更新值并返回true,如果不同,继续取值然后再比较,直至更新完成。这一部分可能比较难懂,这里在理解源码的基础上举个例子来解释。

    深入理解CAS

     

    深入理解CAS
    getAndAddInt源码

     

     深入理解CAS

  4. 变量value用volatile修饰,保证了多线程之间的内存可见性。

为什么使用CAS而不使用synchronized

synchronized是属于独占资源,同一时间段只允许有一个线程来访问,一致性得到了保障,但是并发性下降,而CAS并没有加锁而是进行多次地取值并比较,这样既保障了一致性,又提高了并发性。

CAS缺点

  1. 循环时间长,开销很大。如果CAS失败,会一直进行尝试,如果长时间一直不成功,可能会给CPU带来很大的开销。
  2. 只能保证一个共享变量的原子操作。
  3. 引发ABA问题

未完待续。