cas 的硬件原子性由 cmpxchg 指令加 lock 前缀实现,实际依赖 mesi 缓存一致性协议完成缓存行级独占控制;仅在非对齐访问等极少数场景下才退化为总线锁定,现代 cpu 中占比不足 1%。

CAS 机制在多核 CPU 硬件层面上并不主动“保证总线锁定”,而是优先通过缓存一致性协议(如 MESI)实现缓存行级的独占控制;只有在极少数特定条件下,才会退化为总线锁定。现代 x86 CPU 几乎从不真正锁总线,所谓“总线锁定”是一种历史概念或底层 fallback 机制,不是 CAS 的常规执行路径。
✅ CAS 的硬件原子性靠的是 cmpxchg 指令 + LOCK 前缀
- Java 中的
Unsafe.compareAndSwapInt等方法,最终由 JVM 编译为带lock cmpxchg前缀的汇编指令(x86_64 下)。 -
lock前缀不是一条独立指令,而是对cmpxchg等读-改-写指令的修饰符,它触发 CPU 自动启用硬件级别的串行化保障。 - 这个过程对软件完全透明:你不需要、也无法手动选择“用总线锁还是缓存锁”。
✅ 真正起作用的是缓存一致性协议(MESI)
-
当目标地址落在已缓存、对齐、且处于 Exclusive 或 Modified 状态的缓存行内时:
- CPU 直接在本地 L1/L2 缓存中完成比较与交换;
- 不发总线信号,也不阻塞其他核心访问其他内存地址;
- 效果等价于“缓存锁”,粒度是单个缓存行(通常 64 字节)。
-
当目标缓存行处于 Shared 或 Invalid 状态(即被其他核缓存或未加载)时:
- CPU 发起 RFO(Request For Ownership)请求;
- 其他核收到信号后,将该缓存行置为 Invalid;
- 本核获得独占权后执行
cmpxchg; - 整个过程仍由 MESI 协议协调,不涉及总线锁定。
⚠️ 总线锁定只在极特殊场景下发生
- 非对齐内存访问(例如跨两个缓存行的地址);
- 访问未缓存内存区域(如某些 MMIO 设备寄存器);
- 老式 CPU 或禁用缓存一致性的情况(现代服务器 CPU 基本不存在)。
实测数据显示:99% 以上的 CAS 操作在主流 Intel/AMD 处理器上走的是缓存锁定路径,总线锁属于异常 fallback,不是设计目标。
✅ JVM 和 Java 层面做了适配优化
- HotSpot JVM 会尽量让对象字段内存对齐(例如通过
@Contended注解或字段填充),减少跨缓存行风险; - 在 ARM 等非 x86 架构上,JVM 使用
ldaxr/stlxr等独占加载/存储指令配合 exclusive monitor,语义等价但无lock概念; - 开发者只需关注逻辑正确性,无需干预底层锁机制。
不复杂但容易忽略。











