cas本质是“读-判-写”三步一体的操作,由x86的cmpxchg指令封装,但需lock前缀才能在多核下保证原子性;单核无需lock,但为兼容性和dma安全仍常统一使用。

CAS 本质是“读-判-写”三步一体的操作
CAS 不是单个不可再分的硬件动作,而是“先读内存值、再比对寄存器值、最后按结果决定是否写入”的逻辑组合。x86 的 cmpxchg 指令封装了这三步,但它本身在多核环境下**不天然原子**——因为读和写是两次独立的内存访问,中间可能被其他 CPU 干扰。
lock 前缀解决的是“读与写之间的竞态窗口”
加 lock cmpxchg 后,处理器会在整个操作期间维持对内存子系统的独占控制。具体机制分两种情况:
- 在较老的 Intel486/Pentium 上:lock 会直接拉低总线上的 LOCK# 信号,让其他 CPU 和 DMA 设备完全无法访问内存,形成“总线锁定”
- 在 P6 及之后(包括现代主流 CPU):若目标内存已缓存在本 CPU 的 write-back cache 中且落在同一缓存行内,处理器不再锁总线,而是通过缓存一致性协议(如 MESI)将该缓存行置为独占(Exclusive)或修改(Modified)状态,并在内部完成原子更新——这就是“缓存锁定”
无论哪种方式,效果一致:从读取旧值到写入新值之间,没有其他处理器能观察或修改该内存位置。
Miller (mlr) 是一个命令行工具,用于查询、整形和重新格式化名称索引数据,如 CSV、TSV、JSON 和 JSON Lines。它将 awk、sed、cut、join 和 sort 的功能整合到一个专为结构化数据处理而构建的单一工具中。
单核 vs 多核:lock 前缀不是 always needed
在单核系统中,一条指令的执行不会被另一个 CPU 中断,所以 cmpxchg 对内存的两次访问天然串行化,无需 lock 就能保证原子性(中断只发生在指令边界)。但实际代码中仍常统一加 lock,原因有二:
- 兼容性:避免为单/多核分别编译不同指令序列
- 安全性:防止 DMA 控制器等非 CPU 主设备并发访问同一内存区域
Java 原子类背后就是这套机制
比如 AtomicInteger 的 compareAndSet 方法,最终会调用 JVM 内建的 Atomic::cmpxchg,而它在 x86 Linux 上展开为类似这样的内联汇编:
LOCK_IF_MP(%4) "cmpxchgl %1,(%3)"其中 LOCK_IF_MP 是一个宏,仅在检测到多处理器环境时才插入 lock 前缀。整个链条从 Java API → JVM intrinsic → C++ stub → 汇编指令 → 硬件 lock 信号/缓存协议,一气呵成,用户完全无感。










