问题描述
类似于我的上一个问题,请考虑以下代码
Similar to my previous question, consider this code
-- Initially --
std::atomic<int> x{0};
std::atomic<int> y{0};
-- Thread 1 --
x.store(1, std::memory_order_release);
-- Thread 2 --
y.store(2, std::memory_order_release);
-- Thread 3 --
int r1 = x.load(std::memory_order_acquire); // x first
int r2 = y.load(std::memory_order_acquire);
-- Thread 4 --
int r3 = y.load(std::memory_order_acquire); // y first
int r4 = x.load(std::memory_order_acquire);
在C ++ 11内存模型下,在这种情况下,奇怪的结果 r1==1, r2==0
和r3==2, r4==0
是否可能?如果我将所有std::memory_order_acq_rel
替换为std::memory_order_relaxed
怎么办?
Is the weird outcome r1==1, r2==0
and r3==2, r4==0
possible in this case under the C++11 memory model? What if I were to replace all std::memory_order_acq_rel
by std::memory_order_relaxed
?
在x86上,这样的结果似乎是被禁止的,请参见此SO问题,但是我要问的是C ++ 11内存-一般.
On x86 such an outcome seems to be forbidden, see this SO question but I am asking about the C++11 memory-model in general.
奖励问题:
我们都同意,对于std::memory_order_seq_cst
,古怪的结果在C ++ 11中是不允许的.现在,赫伯·萨特(Herb Sutter)在他着名的 atomic<>
-武器谈话 @ 42:30 std::memory_order_seq_cst
就像std::memory_order_acq_rel
,但 std::memory_order_acquire
-负载可能在std::memory_order_release
-写入.我看不到上面示例中的此附加约束如何防止奇怪的结果.谁能解释?
We all agree, that with std::memory_order_seq_cst
the weird outcome would not be allowed in C++11. Now, Herb Sutter said in his famous atomic<>
-weapons talk @ 42:30 that std::memory_order_seq_cst
is just like std::memory_order_acq_rel
but std::memory_order_acquire
-loads may not move before std::memory_order_release
-writes. I cannot see how this additional constraint in the above example would prevent the weird outcome. Can anyone explain?
推荐答案
问题中的更新的代码(在线程4中交换了x
和y
的负载)确实进行了测试所有线程都同意全球商店订单.
The updated code in the question (with loads of x
and y
swapped in Thread 4) does actually test that all threads agree on a global store order.
在C ++ 11内存模型下,结果r1==1, r2==0, r3==2, r4==0
是允许的,并且实际上可以在POWER上观察到.
Under the C++11 memory model, the outcome r1==1, r2==0, r3==2, r4==0
is allowed and in fact observable on POWER.
在x86上,此结果是不可能的,因为那里其他处理器以一致的顺序看到存储".在顺序一致执行中也不允许这种结果.
On x86 this outcome is not possible, because there "stores are seen in a consistent order by other processors". This outcome is also not allowed in a sequential consistent execution.
脚注1 :这个问题最初是让两个读者都先阅读x
然后阅读y
的.的顺序一致执行是:
Footnote 1: The question originally had both readers read x
then y
. A sequentially consistent execution of that is:
-- Initially --
std::atomic<int> x{0};
std::atomic<int> y{0};
-- Thread 4 --
int r3 = x.load(std::memory_order_acquire);
-- Thread 1 --
x.store(1, std::memory_order_release);
-- Thread 3 --
int r1 = x.load(std::memory_order_acquire);
int r2 = y.load(std::memory_order_acquire);
-- Thread 2 --
y.store(2, std::memory_order_release);
-- Thread 4 --
int r4 = y.load(std::memory_order_acquire);
这将导致r1==1, r2==0, r3==0, r4==2
.因此,这根本不是一个奇怪的结果.
This results in r1==1, r2==0, r3==0, r4==2
. Hence, this is not a weird outcome at all.
要说每个读者看到的商店顺序不同,我们需要他们以相反的顺序阅读,以排除最后一个商店只是被延迟了.
To be able to say that each reader saw a different store order, we need them to read in opposite orders to rule out the last store simply being delayed.
这篇关于是否会在其他线程中始终以相同顺序看到对不同线程中不同位置的两次原子写操作?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!