一、AtomicInteger 是什么
AtomicInteger 是 java.util.concurrent.atomic 包提供的线程安全整型工具类,基于 CAS(Compare-And-Swap)+ volatile + 自旋实现无锁原子操作,用来在多线程下安全更新单个 int 值,性能远好于 synchronized。
- 类继承:
AtomicInteger extends Number implements Serializable - 诞生:JDK 1.5+
- 定位:无锁、非阻塞、轻量级并发工具
二、为什么需要 AtomicInteger
普通 int i++ 不是原子操作,实际分三步:
- 读取
i - 计算
i+1 - 写回
i
多线程下会丢失更新(竞态条件)。传统用 synchronized 或 Lock,但:
synchronized:阻塞、上下文切换、性能差Lock:编码复杂,仍有阻塞
AtomicInteger 用无锁 CAS 自旋,线程不阻塞,只重试,高并发下吞吐更高。
三、核心结构(底层字段)
public class AtomicInteger extends Number implements Serializable {
// 核心值:volatile 保证可见性与禁止指令重排
private volatile int value;
// Unsafe:直接操作内存、执行 CAS 原语
private static final Unsafe unsafe = Unsafe.getUnsafe();
// value 字段在对象内的内存偏移地址
private static final long valueOffset;
static {
try {
// 初始化 valueOffset
valueOffset = unsafe.objectFieldOffset
(AtomicInteger.class.getDeclaredField("value"));
} catch (Exception ex) { throw new Error(ex); }
}
}
- volatile int value:保证多线程立即可见、禁止重排
- Unsafe + valueOffset:直接操作内存,调用 CPU CAS 指令
四、常用 API(原子操作)
1. 构造器
AtomicInteger() // 初始值 0
AtomicInteger(int init) // 指定初始值
2. 基础读写
get():获取当前值set(int newValue):强制设值(volatile 写)lazySet(int newValue):延迟写(不保证立即可见,性能更高)
3. 自增/自减(最常用)
| 方法 | 作用 | 示例(初值5) |
|---|---|---|
getAndIncrement() | 返回旧值,再+1 | 5→返回5 |
incrementAndGet() | 先+1,返回新值 | 5→返回6 |
getAndDecrement() | 返回旧值,再-1 | 5→返回5 |
decrementAndGet() | 先-1,返回新值 | 5→返回4 |
AtomicInteger cnt = new AtomicInteger(0);
cnt.incrementAndGet(); // 原子 +1,返回新值
4. 加减与更新
addAndGet(int delta):加 delta,返回新值getAndAdd(int delta):返回旧值,再加 deltaupdateAndGet(IntUnaryOperator):函数式更新(JDK8+)getAndUpdate(IntUnaryOperator):函数式更新,返回旧值
5. CAS 核心方法
// 如果当前值 == expect,就更新为 update,返回 true;否则 false
boolean compareAndSet(int expect, int update)
- 乐观锁核心:无锁、非阻塞、失败重试
五、底层原理:CAS + 自旋
以 getAndIncrement() 为例(JDK 源码简化):
public final int getAndIncrement() {
int prev, next;
do {
prev = get(); // 1. 读当前值
next = prev + 1; // 2. 计算新值
// 3. CAS:prev 没变才更新,失败就自旋重试
} while (!compareAndSet(prev, next));
return prev;
}
- CAS 原语:
unsafe.compareAndSwapInt(...),CPU 指令级原子 - 自旋重试:失败不阻塞,循环直到成功,高并发下效率远高于锁
六、典型使用场景
- 计数器(点赞数、访问量、ID 生成)
private static final AtomicInteger seq = new AtomicInteger(0);
public static int nextId() {
return seq.incrementAndGet();
}
- 并发状态标记
AtomicInteger status = new AtomicInteger(0);
if (status.compareAndSet(0, 1)) {
// 成功抢占,执行任务
}
- 无锁队列/栈的索引维护
七、优缺点与注意事项
优点
- 无锁、非阻塞:线程不挂起,上下文切换少
- 高性能:高并发下比
synchronized快很多 - 轻量:仅包装
int,无额外对象开销
缺点
- 自旋消耗 CPU:竞争激烈时,空转浪费 CPU
- ABA 问题:值从 A→B→A,CAS 误判未变
- 解决:用
AtomicStampedReference(带版本号)
- 解决:用
- 只能保证单个变量原子:复合操作仍需锁
对比
- 低竞争:
AtomicInteger≈synchronized - 高竞争:
AtomicInteger显著优于synchronized - 超高并发(如 10w+/s):用
LongAdder(分段锁,CAS 更少)
八、总结
- AtomicInteger = 原子 + int:无锁、线程安全、高性能
- 核心:CAS + volatile + 自旋,依赖
Unsafe直接操作内存 - 适用:计数器、状态位、ID 生成等单变量原子场景
- 替代:优先
AtomicInteger;超高并发用LongAdder;需版本控制用AtomicStampedReference