CAS 操作在 JDK 中是通过哪个类来实现的?
参考回答
在 JDK 中,CAS(Compare-And-Swap,比较并交换)操作是通过 Unsafe
类 来实现的。Unsafe
是一个 Java 内部类,提供了直接操作内存和执行底层操作的能力,它是 Java 中实现 CAS 操作的核心。
详细讲解与拓展
1. 什么是 CAS?
CAS 是一种无锁的原子操作机制,常用于实现并发编程中的原子性。它的核心逻辑是:
- 比较内存中的值与预期值。
- 如果相同,就更新为新值。
- 如果不同,则说明其他线程已经修改过该值,CAS 操作失败。
2. CAS 在 JDK 中的实现:Unsafe
类
Unsafe
类简介
Unsafe
是 sun.misc
包下的一个类,提供了一些用于内存操作和底层系统交互的方法。CAS 操作是通过 Unsafe
提供的以下方法实现的:
compareAndSwapInt(Object obj, long offset, int expected, int newValue)
:比较并交换整数值。compareAndSwapLong(Object obj, long offset, long expected, long newValue)
:比较并交换长整型值。compareAndSwapObject(Object obj, long offset, Object expected, Object newValue)
:比较并交换对象引用。
源码示例:Unsafe
类的部分方法
以下是 compareAndSwapInt
的定义:
public final native boolean compareAndSwapInt(Object obj, long offset, int expected, int x);
obj
:要操作的对象。offset
:字段在对象中的内存偏移量。expected
:期望值。x
:要更新的新值。
3. CAS 操作在 JDK 中的应用
1. AtomicInteger
的实现
CAS 操作是 java.util.concurrent.atomic
包下类的核心,例如 AtomicInteger
、AtomicLong
等。
AtomicInteger
源码片段:
private static final Unsafe unsafe = Unsafe.getUnsafe();
private static final long valueOffset;
static {
try {
valueOffset = unsafe.objectFieldOffset
(AtomicInteger.class.getDeclaredField("value"));
} catch (Exception ex) {
throw new Error(ex);
}
}
private volatile int value;
public final int getAndIncrement() {
return unsafe.getAndAddInt(this, valueOffset, 1);
}
public final boolean compareAndSet(int expect, int update) {
return unsafe.compareAndSwapInt(this, valueOffset, expect, update);
}
解释:
value
是一个volatile
变量,用于保证可见性。- 使用
Unsafe.compareAndSwapInt
实现了原子更新。 valueOffset
表示value
在内存中的偏移量,Unsafe
通过偏移量直接操作内存。
2. ReentrantLock
的实现
CAS 操作也被用于实现 ReentrantLock
的公平锁和非公平锁的锁竞争逻辑。
源码片段:
protected final boolean compareAndSetState(int expect, int update) {
return unsafe.compareAndSwapInt(this, stateOffset, expect, update);
}
4. CAS 的优点与缺点
优点
- 无锁机制:避免了传统锁机制的阻塞问题,提高了并发性能。
- 高效:适合高并发场景,特别是对原子操作的需求。
缺点
- ABA 问题
: 如果某个值在中间被其他线程改为另一个值再改回来,CAS 无法检测到。
- 解决方案:引入版本号(如
AtomicStampedReference
)。
-
自旋开销: CAS 操作可能需要反复重试,消耗 CPU 资源。
-
只能保证一个变量的原子性: 对于多个变量的原子操作,需要配合其他机制。
5. 小结
- CAS 操作在 JDK 中通过
Unsafe
类实现,并用于java.util.concurrent.atomic
和ReentrantLock
等核心并发工具中。 Unsafe
提供了底层的compareAndSwapXXX
方法,直接操作内存,实现高效的原子性操作。- 虽然 CAS 提高了并发性能,但也有局限性(如 ABA 问题),需要根据具体场景选择合适的并发控制方案。