本文基于JDK8

什么是CAS?

CAS(compare and swap),比较与交换,CAS实际上是操作系统底层提供的一个原子指令,对于CAS来说有三个值,V(需要修改的内存的地址)、A(预期初始的值)、B(预期修改后的值),简单来说就是当V位置的数据为A时,我们尝试把它修改为B。当多个线程同时进行修改的时候,只有一个线程可以成功,其它线程都会失败,对于失败的线程区别于锁不会挂起而是会继续尝试修改。

那么CAS在JDK里面的应用呢?

像我们熟悉的原子类的一些方法就是和CAS相关

1
2
3
4
public final boolean weakCompareAndSet(int expect, int update) {
// valueOffset == V、expect == A、update == B
return unsafe.compareAndSwapInt(this, valueOffset, expect, update);
}

什么是Unsafe类?

Unsafe类有着类似于C语言指针一样可以操作内存的效果,但是如果不正确的使用Unsafe类可能导致程序出错。

1
2
// Unsafe类是单例实现的
private static final Unsafe theUnsafe;

有两种方式可以获得Unsafe类:

1.把调用Unsafe相关方法的类A所在jar包路径追加到默认的bootstrap路径中

1
java -Xbootclasspath/a: ${path}   // 其中path为调用Unsafe相关方法的类所在jar包路径 

2.反射

1
2
3
Field field = Unsafe.class.getDeclaredField("theUnsafe");
field.setAccessible(true);
return (Unsafe) field.get(null);

那Unsafe类和CAS的关系是什么呢?

AtomicInteger类的一个静态变量valueOffset表示字段value的内存偏移地址,配合AtomicInteger对象的基地址就可以得到CAS的三个基本数中的V

image-20240308193852686

1
2
3
4
5
6
7
private static final long valueOffset;
static {
try {
valueOffset = unsafe.objectFieldOffset
(AtomicInteger.class.getDeclaredField("value"));
} catch (Exception ex) { throw new Error(ex); }
}