CAS的原子性由CPU硬件指令直接保障,Java中Unsafe.compareAndSwapInt最终编译为带lock前缀的cmpxchg指令,通过MESI协议实现缓存行级独占控制,绝大多数情况不锁总线。

CAS 的原子性不是 Java 层面“做出来”的,而是由 CPU 硬件指令直接保障的。Java 中的 Unsafe.compareAndSwapInt 等方法,最终被 JVM 编译为带 lock 前缀的 cmpxchg 指令(x86-64 架构下),lock 并非独立指令,而是修饰读-改-写类指令的硬件语义标记,它告诉 CPU:“请确保这条指令在多核环境下原子执行”。
lock 前缀触发的是缓存行级独占控制,不是总线锁定
现代多核 CPU 几乎从不真正锁总线。lock cmpxchg 执行时,CPU 优先通过 MESI 缓存一致性协议协调各核心缓存状态:
- 若目标变量已缓存在当前 CPU 的 L1/L2 缓存中,且处于 Modified 或 Exclusive 状态,CPU 直接在本地缓存完成比较与交换,仅锁定该缓存行(Cache Line Lock);
- 此时其他核心若要访问同一缓存行,需先通过总线嗅探(bus snooping)使该行失效,再重新获取——整个过程无总线争用,延迟低、吞吐高;
- 总线锁定(Bus Lock)只是极少数 fallback 场景下的兜底行为,例如:地址未对齐、跨缓存行访问、目标内存未被任何核心缓存等,这类情况在现代程序中占比不足 1%。
硬件自动决策,软件完全不可控也不需关心
你写 Java 代码时无法指定用缓存锁还是总线锁,JVM 生成的指令也无需你干预。CPU 在执行 lock cmpxchg 时,会根据当前缓存状态、内存地址对齐性、总线协议等实时条件,动态选择最优路径:
Java开发手册规约集合,基于阿里巴巴Java开发手册(嵩山版)。 涵盖7大维度:编程规约、异常日志、单元测试、安全规约、MySQL数据库、工程结构、设计规约。 当用户需要:(1) 编写或审查Java代码 (2) 检查命名/代码规范 (3) 处理异常和日志 (4) 编写单元测试 (5) 安全编码 (6) 数据库设...
- 没有 API、配置或 JVM 参数能强制启用总线锁;
- 也没有办法绕过 lock 前缀去“手动优化”——去掉它,
cmpxchg就失去多核原子性保障; - 所谓“加锁时间短”,正是因为绝大多数 CAS 走的是缓存行锁路径,而非传统意义上阻塞整条总线的粗粒度锁。
Java 层看到的只是原子语义,背后是硬件协作
AtomicInteger.incrementAndGet() 这类操作看似简单,其可靠性完全依赖于底层硬件协作:
立即学习“Java免费学习笔记(深入)”;
- 每次 CAS 尝试都是一次完整的“读取旧值 → 比较 → 写入新值”硬件原语,中间不可分割、不可中断;
- 多个线程并发调用,最多只有一个能成功更新内存,其余全部失败返回 false,不存在部分更新或中间态;
- volatile 读写保证可见性,而
lock cmpxchg保证“读-比-写”三步的串行化执行——二者配合,构成 Java 原子类的完整基础。
本质上,CAS 不是“靠锁实现原子性”,而是靠 CPU 把一条指令设计成硬件级原子操作,lock 前缀只是激活这个能力的开关。它既不是软件锁,也不是传统意义的排他锁,而是一种由缓存协议支撑的、细粒度的、自动化的硬件同步机制。

















