目录一. 什么是CAS二. Java中关于 CAS 的 API 在哪里三. CAS API方法和参数解析四. CAS的底层实现五. CAS是如何保证多核线程安全的六. CAS的缺点七. 如何避免ABA问题一. 什么是CASCAS的全称是 CompareAndSwap翻译过来就是 比较和替换。CAS的操作包含三个操作数——内存地址期望值新值。如果内存位置的值与期望值匹配那么处理器就会自动将该位置的值更新为新值否则处理器不做任何操作。无论哪种情况它都会在CAS指令之前返回该位置的值。CAS可以理解为 我认为位置V的值应该是A如果有该值则将B放在这个位置否则不更改该位置的值只告诉我这个位置现在的值即可。二. Java中关于 CAS 的 API 在哪里Java中 CAS 的 API 方法定义在 sun.misc.Unsafe 类中Unsafe(不安全的)。如下图所示就是该类中的部分代码圈出来的三个方法 三个方法都有 native 修饰这些方法不是由 Java 语言编写的而是由C语言编写的总之记住一点就行了这些 native 本地CAS方法是用C语言编写的通常也不是让我们 Java 程序员去调用使用的更多见到它们是在源码中碰到它们。三. CAS API方法和参数解析CAS的三个方法作用相似它们都有四个参数我来说一下它们的作用。compareAndSwapObject比较并交换 Object 类型数据compareAndSwapInt比较并交换 Int 类型数据compareAndSwapLong比较并交换 Long 类型数据var1方法要操作的对象var2方法要操作的对象中属性的偏移量(举个例子我们有一个 User 用户对象在堆中存放但我们只获取该 User 对象的其中一个属性值就需要通过偏移量来获取例如 user.name 获取用户名称属性)var3表示想要修改的数据属性当前值意思就是改之前是什么值var4表示想要修改的数据的修改值意思就是想改成什么值四. CAS的底层实现CAS的底层实现是通过调用 JNI 代码来实现的。JNI 全称 java.native.interface 翻译过来就是 Java本地接口方法允许Java调用其它语言而Java中的这三个CAS方法底层是用C语言编写的通过C语言调用底层CPU最终映射到CPU指令集上得以实现。五. CAS是如何保证多核线程安全的现在的计算机大多都是多核心处理器那么在此种情况下系统执行CAS操作之前会先去判断当前系统是否为多核心系统。如果是就会给 总线 加锁尽管有多个线程但只有一个线程能给总线加锁成功加完锁之后就会去执行CAS操作也就是说CAS操作的原子性是平台级别的。而且只能有一个线程在同一时刻能够去执行CAS运算无法多线程并行CAS操作这样就解决了多核线程的安全问题。六. CAS的缺点上面说到了CAS的操作原理比较并替换CAS操作时需要先判断先前的值是否发生变化未变化则CAS变化了则不执行CAS如果说A线程在执行CAS操作之前B线程将需要判断的值 a 改为了 b 然后又从 b 改成了 a。那么当A线程再去执行CAS操作的时候是可以执行成功的因为它不管中间过程只要我线程A在CAS时值未发生变化就可以替换但不能避免发生过变化不影响操作这种情况的发生。举个简单的例子事务A要去对数据库中的字段 num (假设当前值为1)做加一操作事务B在事务A之前先去执行了加一操作值变成了2但是执行过程中发生了异常事务B回滚又从2回滚到了1此时事务A再去对 num 进行加一操作时是可以成功的因为值没有发生改变。这种情况我们通常称为ABA问题。七. 如何避免ABA问题为了解决ABA问题在Java中就引入了版本号这一说法很简单我们执行CAS操作时不是会比较当前值和期望值是否相同吗那我们就再加入一个版本号对当前可能出现ABA问题的数据加上一个版本号每当有一个线程对当前数据发生过修改版本号都会做一次变换即便又改回了原来的值版本号也是不一致的。这样我们在执行CAS操作时不仅要满足为当前值与期望值相等还要满足当前版本号与期望版本号相同只要有一个不同CAS操作就不会成功这样就可以避免ABA问题的出现。