“共识层级解释了读改写原语之间并非只有性能差异。它为无锁数据结构给出选择下界,也说明为什么从弱原语实现强对象时,算法常不得不降低进展保证、限制参与者数量或引入更强硬件操作。”
形式陈述 ​
读改写原语原子地读取位置旧值,依据旧值计算并写回新值,同时返回旧值或成功标志。典型实例包括 test-and-set、fetch-and-add、swap 和 compare-and-swap。“RMW”是类别,不是单一语义;各原语的 Wait-free 表达能力由共识数层级分类。内存序参数还决定跨位置的可见顺序。
直觉
RMW 的关键是读旧值与条件更新共享同一个原子线性化点,其他线程只能看到操作前或操作后的状态,不能插入中间。不同 RMW 原语表达能力不同:fetch-and-add 总会更新,compare-and-swap 只有观察值仍匹配时才更新并报告失败。原子性解决竞态窗口,却不自动解决 ABA、可见性顺序或对象生命周期。
例子与边界
原子 fetch_add(x,1) 可为每个线程返回不同旧值,构造计数器。用普通读后普通写实现同一代码会丢失更新。RMW 可能反复失败或争用,原子性不保证公平;在 ABA 场景中 CAS 看到值恢复相同却忽略中间变化。
CAS 栈会遭遇 ABA:某地址从 A 变为 B 又回到 A 时,旧 CAS 只比较当前位模式,可能误以为中间没有变化。把比较对象扩成 (ptr,version),或使用安全内存回收机制,可把这段历史显式化。即便原语原子,弱内存模型下仍要为发布与获取选择合适的 ordering。
推论与应用
原子操作在共享内存中实现 RMW,构成无锁算法的常用线性化点。test-and-set、fetch-and-add 或 CAS 也可作为自旋锁的获取原语;忙等、FIFO、公平和抢占行为属于锁实现而非 RMW 定义。
RMW 还可实现计数器、无锁链表与工作队列;并发对象的正确性仍需证明所有操作历史可线性化,进展和内存回收是独立义务。原语之间能否 Wait-free 互相实现,应查共识层级,而不能从指令延迟或名称推断。
参考资料
- Maurice Herlihy and Nir Shavit, The Art of Multiprocessor Programming, rev. 1st ed., Morgan Kaufmann, 2012,Chs. 1–18。
- Hagit Attiya and Jennifer Welch, Distributed Computing: Fundamentals, Simulations, and Advanced Topics, 2nd ed., Wiley, 2004,Chs. 1–18。