AtomicInteger 采用无锁自旋机制,通过 volatile 和底层原子指令实现高并发计数;其性能依赖低竞争假设,高并发下需用 LongAdder 分片或退避策略缓解单点热点,ABA 问题对其计数语义无影响。

AtomicInteger 本身不实现“自旋锁”,它用的是无锁自旋机制——即失败后立即重试 CAS,而不是像传统自旋锁那样用于控制临界区访问。它的高并发计数能力来自底层硬件级原子指令与 volatile 协同保障的可见性+原子性,而非锁结构。
自旋不是锁,是失败后的重试逻辑
CAS 操作天然不阻塞线程。当 incrementAndGet() 调用时,内部循环执行:
- 读取当前
value(volatile 保证从主内存读) - 计算新值(如 +1)
- 调用
Unsafe.compareAndSetInt尝试更新 - 若失败(值已被其他线程改),不挂起,直接回到第一步重试
这个循环就是“自旋”,它不持有任何锁对象,也不参与 Monitor 竞争,只是用 CPU 时间换调度开销。
高并发下计数性能靠的是低竞争假设
AtomicInteger 在单点更新场景下高效,前提是竞争不激烈:
- 每次 CAS 映射为一条 CPU 原子指令(如 x86 的
cmpxchg),无锁头、无上下文切换 - volatile 提供内存屏障,确保读写顺序和跨核可见性
- 适合请求统计、开关标志、简单状态递增等写操作频次中低、线程数可控的场景
一旦并发线程数远超核心数,或每微秒多次更新,大量线程在同一地址上反复 CAS 失败,CPU 空转就会明显,吞吐反而下降。
真要扛住高并发,得绕开单点热点
AtomicInteger 的瓶颈在于所有线程争同一个内存地址。解决思路不是优化自旋,而是分散竞争:
- 用 LongAdder 替代:内部维护多个 Cell,线程先尝试本线程专属槽位累加,冲突时扩容,最后 sum() 合并——写吞吐提升数倍
- 按业务维度分片:比如用
ThreadLocal<AtomicInteger>或哈希取模分配多个 AtomicInteger 实例,再定时汇总 - 引入轻量退避:JDK9+ 可在循环中插入
Thread.onSpinWait(),提示 CPU 进入节能等待态,降低空转功耗
这些都不是给 AtomicInteger “加锁”或“改造自旋”,而是跳出单变量模型,用架构手段稀释竞争。
ABA 问题对计数器基本无影响
计数器只关心最终数值是否正确,+1 操作不依赖中间状态。即使发生 ABA(比如值从 5→6→5),只要 CAS 成功,结果仍是 6,语义不变。只有在涉及引用变更的结构(如无锁栈)中才需用 AtomicStampedReference 加版本号。


















