“SC for DRF 不是脱离语言后仍成立的一条无条件定理,而是一族由内存模型参数化的保证。设模型 $M$ 规定普通访问、原子访问、同步操作及 happens before 的生成规则。常见…”
形式陈述 ​
内存一致性模型是共享内存系统中程序、编译器与硬件之间的可观察行为合同。对一个程序
其中
不同语言和 ISA 会选择不同关系与公理;这份元模型只说明证明对象。若
读值规则、原子性和未同步访问的语义都必须包含在合同内。并发对象历史只记录方法调用与返回,可由底层执行投影得到;它适合线性一致性等对象级规格,却丢失
Coherence 通常逐地址约束写序与读值,顺序一致性则要求所有内存操作共享一个保程序顺序的全序。线性一致性作用于高层对象操作,并额外保持不重叠调用的实时先后。单地址 coherence 无法决定跨地址观察顺序,SC 也没有线性一致性的实时量词。
直觉
处理器会把写暂存在 store buffer,编译器会移动互不依赖的操作,缓存协议会让传播分阶段完成;逐条等待全局可见会牺牲性能。程序证明却需要知道哪些观察绝不会出现。内存模型把优化自由与推理义务同时写成约束:同步原语买回哪些顺序,普通访问在缺少同步时还剩什么语义。
因此模型不是“处理器实际按什么顺序执行”的录像,而是对所有允许观察的公理化包络。一个实现可以内部乱序,只要对外执行仍落在集合内;一次测试从未观察到某结果,也不能证明模型禁止它。
例子与边界
store-buffering 测试从
线程 P: x = 1; r1 = y
线程 Q: y = 1; r2 = x
若两次写先停留在各自 store buffer,随后的读可在对方写尚未传播时取得初值,于是出现
另一条消息发布执行为:线程
缓存一致协议即使保证所有核心按同一顺序观察地址
语言模型、处理器 ISA 模型和分布式副本一致性可能共享“弱”“因果”“顺序”等词,却有不同操作粒度与故障假设。跨层正确性需要证明编译器映射把每个目标执行精化为源模型允许的执行;名称相似不能代替这项映射。某些模型还专门限制 out-of-thin-air 值,单靠局部读写顺序无法排除这种全局循环。
推论与应用
弱内存算法的证明通常分两步:先证明语言层 happens-before、原子写序与读值满足不变量,再验证编译器和 ISA 映射保持这些边。互斥锁、release/acquire、顺序一致原子与栅栏只是构造约束的不同工具,不应统一替换成模糊的“加一道屏障”。
无数据竞争程序在特定语言模型下可能获得 SC-for-DRF 保证,但其“race-free”定义、原子操作范围与结论各不相同。这是一条模型定理,不是所有共享内存系统的默认事实。
设计并发算法时,必须把证明依赖的顺序关系映射到目标语言和处理器提供的原语。仅在某台机器上重复测试未见异常不能替代模型证明,因为被允许但罕见的执行仍可能在不同编译、核心或负载下出现。
模型检查可以把有限程序、候选内存模型和违例条件联合编码,搜索某个允许轨迹是否产生禁用观察。得到反例说明该模型仍容许该行为;未在给定界内找到反例,只是验证算法在当前状态空间上的结论,不会把弱内存模型改写为顺序一致。
参考资料
- Leslie Lamport, “How to Make a Multiprocessor Computer That Correctly Executes Multiprocess Programs,” IEEE Transactions on Computers C-28(9), 1979, pp. 690–691。
- Sarita V. Adve and Kourosh Gharachorloo, “Shared Memory Consistency Models: A Tutorial,” Computer 29(12), 1996, pp. 66–76。
- Mark Batty et al., “The C11 and C++11 Concurrency Model,” POPL 2011, pp. 55–66。