问题描述
在C ++内存模型中,所有加载和所有顺序一致的操作的存储都具有总顺序.我想知道这如何与具有其他内存顺序的操作(在顺序一致的加载之前/之后进行排序)交互.
In the C++ memory model, there is a total order on all loads and stores of all sequentially consistent operations. I'm wondering how this interacts with operations that have other memory orderings that are sequenced before/after sequentially consistent loads.
例如,考虑两个线程:
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中的断言不会触发?
Is it guaranteed that the assertion in T2 cannot fire?
我正在这里寻找标准的详细引用.特别是,我认为这需要证明从T1中的b
与商店中的同步到T2中的b
的负载,以便确定发生到a
线程间的存储在a
加载之前,但据我所知,标准说memory_order_seq_cst
存储与负载同步,但并非相反.
I'm looking for detailed citations of the standard here. In particular I think this this would require showing that the load from b
in T1 synchronizes with the store to b
in T2 in order to establish that the store to a
inter-thread happens before the load from a
, but as far as I can tell the standard says that memory_order_seq_cst
stores synchronize with loads, but not the other way around.
推荐答案
如果满足所有必要要求,它们就会执行;在您的示例代码中,assert
可以触发
They do if all necessary requirements are met; in your example code, the assert
can fire
此总顺序适用于seq_cst
操作本身.孤立地,store(seq_cst)
具有发布语义,而load(seq_cst)
具有获取语义.
This total order applies to the seq_cst
operations themselves.. In isolation, a store(seq_cst)
has release semantics, whereas a load(seq_cst)
has acquire semantics.
因此,按照获取/释放排序规则,相对于seq_cst
操作,对具有非seq_cst
排序的原子操作(或非原子操作)进行了排序:
Therefore, atomic operations with non-seq_cst
ordering (or non-atomic operations) are ordered with respect to seq_cst
operations per the acquire/release ordering rules:
-
store(seq_cst)
操作不能使用在其之前已排序的任何内存操作(即,按程序顺序排在较早的位置)进行重新排序.. -
load(seq_cst)
操作不能用其后顺序的任何内存操作重新排序.
- a
store(seq_cst)
operation cannot be reordered with any memory operation that is sequenced before it (i.e. comes earlier in program order).. - a
load(seq_cst)
operation cannot be reordered with any memory operation that is sequenced after it.
在您的示例中,尽管在b.load(seq_cst)
之后对T1
中的c.store(relaxed)
进行了排序(线程间)(load
是获取操作),相对于b.store(seq_cst)
,T2
中的c.load(relaxed)
是无序的(这是一个释放操作,但不会阻止重新排序).
In your example, although c.store(relaxed)
in T1
is ordered (inter-thread) after b.load(seq_cst)
(the load
is an acquire operation),c.load(relaxed)
in T2
is unordered with respect to b.store(seq_cst)
(which is a release operation, but it does not prevent the reordering).
您也可以查看a
上的操作.由于没有针对任何对象进行排序,因此a.load(relaxed)
可以返回0
,从而导致assert
触发.
You can also look at the operations on a
. Since those are not ordered with respect to anything, a.load(relaxed)
can return 0
, causing the assert
to fire.
这篇关于C ++内存模型:seq_cst加载是否与seq_cst存储同步?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!