原子类
约 785 字大约 3 分钟
2025-08-27
定义
Java 原子类 是指 java.util.concurrent.atomic 包中提供的一组线程安全的类,用于实现无锁(lock-free)的变量操作。常见的原子类包括:
- 原子更新基本类型:如
AtomicInteger、AtomicLong、AtomicBoolean - 原子更新数组:如
AtomicIntegerArray、AtomicLongArray、AtomicReferenceArray - 原子更新引用:如
AtomicReference、AtomicStampedReference - 原子更新属性:如
AtomicIntegerFieldUpdater、AtomicLongFieldUpdater、AtomicReferenceFieldUpdater
这些类通过 CAS(Compare-And-Swap) 机制以及底层硬件支持,实现对变量的线程安全操作,而无需使用传统的锁(如 synchronized 或 ReentrantLock)。
原理
为什么原子类的操作是原子性的?
Java 原子类的操作之所以具备原子性,核心依赖于 CAS(Compare-And-Swap) 操作,该机制基于 CPU 的原子指令(如 x86 平台的 CMPXCHG 指令)实现。CAS 是一种乐观锁机制,其基本流程如下:
- 比较:检查当前内存中的值是否等于预期值。
- 交换:如果相等,则将内存中的值更新为新值。
- 返回结果:返回操作是否成功。
原子类底层通过 Unsafe 类实现 CAS 操作。Unsafe 是 Java 提供的一个可以进行底层内存操作的类,其方法直接通过 JNI(Java Native Interface) 调用 C/C++ 实现,最终转化为一条 CPU 的原子指令。
AtomicInteger 的 incrementAndGet
public final int incrementAndGet() {
return unsafe.getAndAddInt(this, valueOffset, 1) + 1;
}其中 getAndAddInt() 方法通过循环不断尝试 CAS 操作,直到成功为止,确保操作具备原子性。
CAS 原理伪代码
boolean compareAndSwap(int* address, int expectedValue, int newValue) {
if (*address == expectedValue) {
*address = newValue;
return true;
}
return false;
}该伪代码仅用于说明逻辑,实际实现依赖于硬件平台的原子指令。
使用场景
Java 原子类适用于需要轻量级线程安全操作的场景,尤其是在并发环境中仅需对单一变量进行原子更新时。其优势在于:
- 简单:API 设计简洁,易于使用。
- 高效:避免了锁的上下文切换和阻塞开销,资源占用低。
- 线程安全:通过 CAS 操作保证并发下的数据一致性。
常见应用场景
计数器 适用于高并发环境下的请求计数、任务完成数统计、在线用户数统计等。
AtomicInteger requestCount = new AtomicInteger(0); requestCount.incrementAndGet();状态标识 在多线程环境中用于维护某个状态标志(如是否初始化完成)。
AtomicBoolean initialized = new AtomicBoolean(false); if (initialized.compareAndSet(false, true)) { // 执行初始化逻辑 }累加器 用于并行计算中的中间结果聚合(如并行流中的计数器)。
高性能缓存或状态控制 在需要频繁读写共享变量的场景中,使用原子类可以避免锁竞争,提高系统吞吐量。
适用性对比
| 机制 | 原子类 | synchronized / Lock |
|---|---|---|
| 实现方式 | CAS(无锁) | 阻塞式锁 |
| 性能 | 高效(无阻塞) | 有上下文切换开销 |
| 适用粒度 | 单个变量的操作 | 任意代码块或变量 |
| 适用场景 | 简单、高频的共享变量更新 | 复杂逻辑或临界区保护 |