原子类与 CAS
原子类位于 java.util.concurrent.atomic 包,基于 CAS 实现无锁并发。
CAS 原理
CAS(Compare And Swap)是硬件级别的原子操作:
Java
CAS(V, E, N)
V:变量当前值
E:期望值
N:新值
如果 V == E,则 V = N(更新成功)
否则不更新(更新失败)
CAS 特点
| 优点 | 缺点 |
|---|---|
| 无锁,高并发性能好 | 高竞争时自旋开销大 |
| 不阻塞线程 | 只保证单变量原子性 |
| CPU 级原子指令 | ABA 问题 |
常用原子类
| 类名 | 作用 |
|---|---|
| AtomicInteger | 整数原子操作 |
| AtomicLong | 长整数原子操作 |
| AtomicBoolean | 布尔原子操作 |
| AtomicReference | 引用原子操作 |
| AtomicIntegerArray | 整数数组原子操作 |
| LongAdder | 高并发计数器(JDK 8) |
AtomicInteger 使用
Java
AtomicInteger count = new AtomicInteger(0);
// 获取值
int value = count.get();
// 设置值
count.set(10);
// 原子自增
count.incrementAndGet(); // 自增并返回新值
count.getAndIncrement(); // 返回旧值后自增
// 原子自减
count.decrementAndGet();
count.getAndDecrement();
// 原子加法
count.addAndGet(5);
count.getAndAdd(5);
// CAS 更新
count.compareAndSet(10, 20); // 当前值为 10 则更新为 20
// 函数式更新
count.updateAndGet(x -> x * 2); // 计算后返回新值
count.getAndUpdate(x -> x + 1); // 返回旧值
AtomicReference 使用
Java
AtomicReference<User> ref = new AtomicReference<>(new User("张三"));
User oldUser = ref.get();
User newUser = new User("李四");
ref.compareAndSet(oldUser, newUser); // 原子更新引用
LongAdder 高并发计数
Java
LongAdder adder = new LongAdder();
adder.increment(); // 增加 1
adder.add(100); // 增加 100
long sum = adder.sum(); // 获取总和
adder.reset(); // 重置
LongAdder vs AtomicLong:LongAdder 使用多个 Cell 分散热点,高并发写入性能远优于 AtomicLong。适合高并发计数场景。
AtomicLong vs LongAdder
| 特性 | AtomicLong | LongAdder |
|---|---|---|
| 写性能 | 高竞争时下降 | 高并发下稳定高效 |
| 读性能 | 立即返回 | 需汇总 Cell |
| 适用场景 | 低并发计数 | 高并发计数 |
ABA 问题
问题说明
Java
线程1:CAS(A, B) → CAS(B, A) // A → B → A
线程2:CAS(A, C) // 看到的是 A,但实际已被修改过
线程2 认为 A 未变,但实际经历了 A → B → A。
解决方案:AtomicStampedReference
text
AtomicStampedReference<Integer> ref = new AtomicStampedReference<>(100, 0);
int[] stampHolder = new int[1];
Integer value = ref.get(stampHolder); // 获取值和版本号
int stamp = stampHolder[0];
ref.compareAndSet(100, 200, stamp, stamp + 1); // 带版本号 CAS
版本号每次更新递增,解决 ABA 问题。
Unsafe 类
CAS 底层依赖 Unsafe 类:
text
// Unsafe 提供 CAS 方法(内部使用,不建议直接调用)
unsafe.compareAndSwapInt(obj, offset, expect, update);
unsafe.compareAndSwapLong(obj, offset, expect, update);
unsafe.compareAndSwapObject(obj, offset, expect, update);
Unsafe 说明:内部 API,不推荐直接使用。原子类封装了 Unsafe 操作。
原子类 vs synchronized
| 特性 | 原子类 | synchronized |
|---|---|---|
| 实现方式 | CAS 无锁 | JVM 锁 |
| 适用范围 | 单变量 | 代码块/方法 |
| 性能 | 高并发下更优 | JDK 6 后差距小 |
| 功能限制 | 只能单变量 | 可保护多个操作 |
要点总结
- CAS:比较并交换,硬件级原子操作
- 原子类基于 CAS,无锁并发,性能优于 synchronized
- AtomicInteger/AtomicLong:整数原子操作
- AtomicReference:引用原子操作
- LongAdder:高并发计数器,性能优于 AtomicLong
- ABA 问题:可用 AtomicStampedReference 加版本号解决
- 原子类只保证单变量原子性,复合操作需其他机制
- 高并发计数推荐 LongAdder
📝 发现内容有误?点击此处直接编辑