在C++内存模型中,所有加载和存储的所有顺序一致的操作都有一个总顺序。我想知道这是如何与具有其他内存顺序的操作交互的,这些操作在顺序一致的加载之前/之后进行排序。
例如,考虑两个线程:
std::atomic<int> a(0);
std::atomic<int> b(0);
std::atomic<int> c(0);
//////////////
// Thread T1
//////////////
// Signal that we've started running.
a.store(1, std::memory_order_relaxed);
// If T2's store to b occurs before our load below in the total
// order on sequentially consistent operations, set flag c.
if (b.load(std::memory_order_seq_cst) == 1) {
c.store(1, std::memory_order_relaxed)
}
//////////////
// Thread T2
//////////////
// Blindly write to b.
b.store(1, std::memory_order_seq_cst)
// Has T1 set c? If so, then we know our store to b occurred before T1's load
// in the total order on sequentially consistent operations.
if (c.load(1, std::memory_order_relaxed)) {
// But is this guaranteed to be visible yet?
assert(a.load(1, std::memory_order_relaxed) == 1);
}它能保证T2中的断言不能触发吗?
我在这里找标准的详细引文。特别是,我认为这需要显示来自b在T1中的负载与存储在T2中的b同步,以便确定到a线程间的存储发生在从a加载之前,但据我所知,标准说memory_order_seq_cst存储与负载同步,而不是相反。
发布于 2017-11-28 01:53:40
seq_cst加载与seq_cst存储同步吗?
如果满足了所有必要的要求,就会这样做;在示例代码中,assert可以触发
第29.3.3节 对于所有的memory_order_seq_cst操作,都应该有一个单一的总订单S
这个总顺序适用于seq_cst操作本身。孤立地说,store(seq_cst)具有发布语义,而load(seq_cst)具有获取语义。
§29.3.1-2 atomics.order memory_order_release、memory_order_acq_rel和memory_order_seq_cst: 存储操作对受影响的内存位置执行释放操作。 . §29.3.1-4 atomics.order memory_order_acquire、memory_order_acq_rel和memory_order_seq_cst: 加载操作对受影响的存储器位置执行获取操作。
因此,具有非seq_cst排序(或非原子操作)的原子操作根据获取/发布排序规则对seq_cst操作进行排序:
store(seq_cst)操作不能与在其之前进行排序的任何内存操作重新排序(即程序顺序较早)。load(seq_cst)操作不能与其后排序的任何内存操作重新排序。在您的示例中,虽然c.store(relaxed) in T1是在b.load(seq_cst) ( load是获取操作)之后排序的(线程间),但T2中的c.load(relaxed)对于b.store(seq_cst) (这是一个发布操作,但它并不阻止重新排序)是无序的。
您还可以查看a上的操作。由于没有对任何内容进行排序,所以a.load(relaxed)可以返回0,从而导致assert触发。
https://stackoverflow.com/questions/47520748
复制相似问题