compareAndSet怎么用
compareAndSet是 Java 中原子操作类(如 AtomicBoolean, AtomicInteger等)提供的一个关键方法,用于实现无锁的线程安全操作。以下是详细解释:
1. 方法定义(以 AtomicBoolean为例)
public final boolean compareAndSet(boolean expect, boolean update)2. 工作原理(CAS 操作)
这是一个原子操作(不会被线程调度打断),执行逻辑如下:
if (当前值 == expect) {当前值 = update;return true; // 修改成功
} else {return false; // 修改失败
}3. 在您代码中的具体应用
private static final AtomicBoolean isRunning = new AtomicBoolean(false);public static void init() {// 尝试将状态从 false 改为 trueif (!isRunning.compareAndSet(false, true)) {logger.info("初始化已在执行中,跳过本次操作");return;}try {// 执行初始化逻辑...} finally {isRunning.set(false); // 重置状态}
}4. 关键特点
特性 | 说明 |
|---|---|
原子性 | 整个比较+设置操作是CPU指令级的原子操作 |
无锁 | 不需要 |
线程安全 | 适合高并发场景的状态管理 |
轻量级 | 比传统锁性能更高 |
5. 与传统 synchronized的对比
// 传统方式(有锁)
synchronized(lock) {if (!isRunning) {isRunning = true;// 执行逻辑...}
}// CAS方式(无锁)
if (atomicBoolean.compareAndSet(false, true)) {// 执行逻辑...
}6. 什么场景更合适?
启动顺序控制:
@Order(Integer.MIN_VALUE)可能被多个 Runner 使用防御性编程:防止意外通过反射等方式多次调用
init()性能优化:避免不必要的锁竞争
7. 底层实现
实际使用的是 CPU 的 CAS 指令(Compare-And-Swap),现代处理器(x86 的 CMPXCHG指令)都直接支持这种原子操作。
8. 典型应用场景
状态标志管理(如您的 isRunning)
计数器(AtomicInteger)
无锁数据结构(ConcurrentHashMap 的桶操作)
自旋锁实现
使用 compareAndSet比原来的 volatile + synchronized方案更简洁高效,且能提供更强的线程安全保障。
