✅ 核心速览 :
java.util.concurrent.atomic包提供无锁、高性能的线程安全工具,基于 CAS (Compare-And-Swap) 与 VarHandle(JDK 9+)实现,避免 synchronized阻塞开销,适用于单变量原子更新。
核心原理:通过 CPU CAS 指令(比较并交换)保证原子性;JDK 9 起推荐 VarHandle(替代 Unsafe),JDK 21 原子类全面基于 VarHandle。
关键分类:
- 基本类型:AtomicInteger(32位)、AtomicLong(64位)、AtomicBoolean(仅布尔值,无算术操作);
- 引用类型:AtomicReference(对象引用)、AtomicStampedReference(带版本号解决ABA)、AtomicMarkableReference(带标记简化ABA);
- 数组类型:AtomicIntegerArray等(原子更新数组单个元素);
- 高并发优化:LongAdder/DoubleAdder(分段累加,高并发计数性能远超 AtomicLong)。
原子类是 java.util.concurrent.atomic 包下的一组高性能、无锁(lock-free)线程安全工具,用于在多线程环境下安全地更新单个变量,无需使用 synchronized 或 ReentrantLock。它们是实现无锁并发编程的核心组件。
核心原理:CAS 与 VarHandle
-
count++的非原子性该操作在字节码层面包含三步:读取 → 加1 → 写回。在多线程下,这些步骤可能交错执行,导致更新丢失。
-
传统方案:加锁
使用
synchronized可以保证安全,但会带来上下文切换、竞争和阻塞的开销。 -
原子类方案:CAS
原子类通过 CPU 的 CAS (Compare-And-Swap) 指令实现原子操作,避免了锁的开销,在低到中等竞争场景下性能显著优于锁。其早期实现依赖
sun.misc.Unsafe,但从 JDK 9 起,官方推荐使用java.lang.invoke.VarHandle作为底层标准 API。 -
VarHandle的核心方法
VarHandle提供了更安全、可移植的底层访问能力,支持以下操作:compareAndSet(expected, value)getAndSet(value)getAndAdd(delta)getAcquire()/setRelease()
-
JDK 21 及以后
所有原子类(如
AtomicInteger)内部已全面基于VarHandle实现。
原子类分类与用法
1、基本类型原子类
用于原子化地更新 boolean、int、long 等基本类型。
| 类 | 说明 | 常用方法 |
|---|---|---|
AtomicBoolean |
原子布尔值 | get(), set(newValue), compareAndSet(expect, update), getAndAdd(delta) |
AtomicInteger |
原子整型 (32位) | 同上 |
AtomicLong |
原子长整型 (64位) | 同上 |
2、引用类型原子类
用于原子化地更新对象引用,解决对象引用的并发问题。
| 类 | 说明 | 示例 |
|---|---|---|
AtomicReference<T> |
原子引用 | AtomicReference<String> ref = new AtomicReference<>("hello"); ref.compareAndSet("hello", "world"); |
AtomicMarkableReference<T> |
带 boolean 标记的引用 | 用于解决 ABA 问题的简化方案。 |
AtomicStampedReference<T> |
带 int "戳"的引用 | 通过版本号解决更通用的 ABA 问题。 |
3、数组类型原子类
保证对数组中单个元素的操作是原子的,而非整个数组。
| 类 | 说明 | 注意 |
|---|---|---|
AtomicIntegerArray |
原子整型数组 | 操作指定索引的元素。 |
AtomicLongArray |
原子长整型数组 | 同上。 |
AtomicReferenceArray<T> |
原子引用数组 | 同上。 |
4、高并发优化类 (Java 8+)
LongAdder 和 DoubleAdder 专为高并发写场景(如计数器)设计。在激烈竞争下,AtomicLong 因 CAS 失败重试频繁而性能下降,而 LongAdder 通过分段累加(cell 机制)大幅降低了竞争,性能更优。
常见误区
-
误区 1:
atomic.get() + 1是原子操作java
// 错误!非原子操作
int newVal = atomic.get() + 1;
atomic.set(newVal);
必须使用
incrementAndGet()或getAndIncrement()等原子方法。 -
误区 2:
compareAndSet一定会成功在高竞争或 ABA 问题下可能失败,通常需要配合循环重试逻辑。
LongAdder在高并发计数场景下是更优选择。
最佳实践
- 优先使用
LongAdder/DoubleAdder:作为计数器,尤其在写并发高的场景。 - 避免复合操作 :如
if (atomic.get() < 100) atomic.increment();,这需要外部同步来保证原子性。 - 勿用于复杂状态机 :对于复杂的状态流转,应使用
synchronized或java.util.concurrent中的高级工具(如Phaser,StampedLock)。 - 使用标准 API :在 JDK 9+ 中,应使用
VarHandle而非sun.misc.Unsafe。
一键三连,让我的信心像气球一样膨胀!