面试官:CAS你知道吗?
你:嗯知道,CAS就是Compare and Swap,是项乐观锁技术。
面试官:原理?
答:CAS是一种乐观锁机制,具体实现为 Unsafe类 + 自旋,通过Unsafe类提供硬件级别的原子性操作保证了并发安全,加上自旋操作,解决了 synchronized 在多线程环境下会出现的线程阻塞,唤醒切换,以及用户态内核态间的切换操作所带来的消耗。在由此扩展到AtomicInteger
,这样就踏实了!
CAS 基本原理
CAS 主要包括两个操作:Compare
和Swap
,有人可能要问了:两个操作能保证是原子性吗?可以的。
CAS 是一种系统原语
,原语属于操作系统用语,原语由若干指令组成,用于完成某个功能的一个过程,并且原语的执行必须是连续的,在执行过程中不允许被中断,也就是说 CAS 是一条 CPU 的原子指令,由操作系统硬件来保证。
在 Intel 的 CPU 中,使用 cmpxchg 指令。
回到 Java 语言,JDK 是在 1.5 版本后才引入 CAS 操作,在sun.misc.Unsafe
这个类中定义了 CAS 相关的方法。
public final native boolean compareAndSwapObject(Object o, long offset, Object expected, Object x);
public final native boolean compareAndSwapInt(Object o, long offset, int expected, int x);
public final native boolean compareAndSwapLong(Object o, long offset, long expected, long x);
可以看到方法被声明为native
,如果对 C++ 比较熟悉可以自行下载 OpenJDK 的源码查看 unsafe.cpp,这里不再展开分析。
CAS 在 Java 语言中的应用
在 Java 编程中我们通常不会直接使用到 CAS,都是通过 JDK 封装好的并发工具类来间接使用的,这些并发工具类都在java.util.concurrent
包中。
J.U.C 是
java.util.concurrent
的简称,也就是大家常说的 Java 并发编程工具包,面试常考,非常非常重要。
目前 CAS 在 JDK 中主要应用在 J.U.C 包下的 Atomic 相关类中。
比如说 AtomicInteger 类就可以解决 i++ 非原子性问题,通过查看源码可以发现主要是靠 volatile 关键字和 CAS 操作来实现。
弊端CAS虽然优点很多,但是也有三个大问题:
- ABA问题: