如何理解C++20中顺序一致性排序的变更及示例疑惑
P0668R5对C++顺序一致性排序的修改及示例解析
示例代码与观测结果
x和y的初始值为0,三个线程的执行代码如下:
// 线程1: x.store(1, std::memory_order_seq_cst); // A y.store(1, std::memory_order_release); // B // 线程2: r1 = y.fetch_add(1, std::memory_order_seq_cst); // C r2 = y.load(std::memory_order_relaxed); // D // 线程3: y.store(3, std::memory_order_seq_cst); // E r3 = x.load(std::memory_order_seq_cst); // F
根据P0668R5提案,允许观测到结果:r1=1、r2=3、r3=0,但该结果在修改前的C++标准中是不被允许的。
旧标准的矛盾点
当前标准不允许上述结果:所有std::memory_order_seq_cst访问必须处于单一全序中,该全序需满足F在A之前(因为F未观测到A的存储),A必须在C之前(因为A先行于C),C必须在E之前(因为fetch_add未观测到E的存储,而线程2的加载强制E处于修改顺序的末尾)。但这是不允许的,因为标准要求先行顺序与顺序一致性排序一致,而全序末尾的E先行于开头的F。
C++20的修改方案
C++20通过修改强先行关系(strongly happens-before)的定义解决了这一矛盾:旧标准中的先行关系被重命名为普通先行关系,新的强先行关系对约束条件做了收紧。根据新规则,尽管A普通先行于C,但A并不强先行于C,因此A不需要在seq_cst的单一全序中排在C之前。
疑问与待解释点
我对修改后的结果存在疑问:根据cppreference,该示例中std::memory_order_seq_cst的单一全序为C-E-F-A(不清楚原因)。但根据先行规则,A仍先行于C,因此A的副作用应对C可见。这是否意味着在线程2观测到的修改顺序中A排在C之前?若是,是否意味着所有线程观测到的单一全序不一致?恳请详细解释上述示例。
内容的提问来源于stack exchange,提问作者Pluto
相关产品推荐
相关产品推荐

