AtomicLong 通过 CPU 硬件级 CAS 指令实现无锁原子更新,将读取、比较、写入合并为一条不可中断操作,配合 volatile 语义和循环重试机制,在高并发下显著优于 synchronized。

AtomicLong 通过底层 CAS(Compare-And-Swap)指令实现无锁原子更新,避免了 synchronized 的线程阻塞与上下文切换开销,在高并发计数场景下显著提升吞吐量。
CAS 是怎么做到“一次比较、一次交换”的
CAS 是 CPU 硬件支持的原子指令(如 x86 的 cmpxchg),它把“读取当前值→比对预期值→写入新值”三步合并为一条不可中断的操作。Java 通过 Unsafe.compareAndSwapLong 调用该指令,保证整个过程要么全部成功,要么完全不执行。
AtomicLong 的 incrementAndGet() 方法内部就是循环尝试 CAS:
- 先用 volatile 语义读取当前值 V
- 计算新值 B = V + 1
- 调用 CAS(V, V, B):仅当内存中仍是 V,才设为 B;否则重试
为什么比 synchronized 快得多
synchronized 是重量级锁,竞争激烈时线程会挂起、唤醒,带来调度开销和延迟。而 AtomicLong 的 CAS 在低/中等竞争下几乎不阻塞:
- 单次 CAS 成功耗时约 1 个 CPU 周期,远低于锁获取成本
- 实测在 8 核机器上,AtomicLong 可达约 1800 万次/秒操作,synchronized 计数器仅约 120 万次/秒
- 没有锁对象监视器、无死锁风险、无线程状态切换
高并发下还能进一步优化:用 LongAdder 替代 AtomicLong
当 QPS 极高(如每秒数十万次更新)时,所有线程争抢同一个 CAS 地址会造成大量自旋失败,浪费 CPU。LongAdder 采用分段策略缓解热点:
- 内部维护一个 base 值 + 一组 Cell 数组
- 线程哈希选择不同 Cell 更新,冲突概率大幅降低
- 最终 sum() 时汇总 base 和所有非空 Cell
- 适合“写多读少”的统计类场景,性能比 AtomicLong 高 3–5 倍
使用时要注意的细节
CAS 不是万能的,实际用好 AtomicLong 还需注意:
- 必须配合 volatile 语义——value 字段被声明为 volatile,确保每次读都从主内存获取最新值
- ABA 问题虽不影响计数器正确性(+1 操作不依赖中间状态),但在更复杂逻辑中需警惕
- 避免在 long 值极大时频繁调用 get() 再 increment(),应优先使用 incrementAndGet() 等原子组合方法
- 不要滥用:若业务逻辑包含多步依赖(如“先查再改”),CAS 自旋可能失效,此时需考虑锁或事务
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











