Java原子类通过CPU的CAS指令实现无锁累加,配合volatile保证可见性与有序性,采用自旋重试的乐观并发策略;但不支持多步复合操作的原子性。

Java 中的原子类(如 AtomicInteger)实现无锁高效累加,核心靠的是 **CPU 提供的 CAS(Compare-And-Swap)指令**,配合 volatile 变量的可见性保证,而不是传统 synchronized 或锁机制。
底层依赖硬件级 CAS 指令
CAS 是一种原子性的 CPU 指令,它能在一个不可分割的操作中完成“比较并更新”:只有当内存地址当前值等于预期旧值时,才把该地址的值设为新值,并返回是否成功。JVM 将 Unsafe.compareAndSwapInt() 等方法映射到底层平台对应的 CAS 汇编指令(如 x86 的 cmpxchg)。这避免了线程挂起、上下文切换等锁开销。
- CAS 成功 → 更新完成,继续执行
- CAS 失败 → 说明有其他线程抢先修改了值,当前线程会重读最新值,再尝试下一轮 CAS(自旋)
- 整个过程不阻塞、不加锁,属于乐观并发策略
volatile 保障可见性与有序性
原子类内部用 volatile 修饰核心字段(如 AtomicInteger.value),确保:
- 每次读取都从主内存获取最新值(禁止寄存器缓存)
- 每次写入都立即刷回主内存(对其他线程可见)
- 禁止相关读写指令重排序,配合 CAS 构成完整的 happens-before 关系
没有 volatile,CAS 可能读到过期缓存值,导致误判和重复更新。
立即学习“Java免费学习笔记(深入)”;
自旋重试 + 有限失败处理
像 incrementAndGet() 这类方法,本质是循环执行 CAS:
- 读取当前值
current - 计算新值
next = current + 1 - 用 CAS 尝试把
current更新为next - 失败则重新读取,再试——直到成功为止
这种自旋在竞争不激烈时极快;高竞争下虽有少量 CPU 浪费,但相比锁的阻塞开销仍更轻量。JDK 8+ 在极端场景下还引入了 LongAdder 等分段累加结构,进一步降低 CAS 冲突概率。
不支持复合操作,需谨慎组合
CAS 本身只保证单次读-改-写原子性,多个原子操作连用(如先 get 再 increment)并不天然原子。例如:
if (ai.get() < 10) ai.incrementAndGet(); // 非原子!存在竞态
这类逻辑需用 compareAndSet() 手动构造,或改用 StampedLock、ReadWriteLock 等更高级同步工具。



















