zxy*_*122 1 c++ multithreading atomic memory-model stdatomic
#include <atomic>
#include <thread>
#include <assert.h>
std::atomic<bool> x,y;
std::atomic<int> z;
void write_x()
{
x.store(true,std::memory_order_seq_cst); // 1
}
void write_y()
{
y.store(true,std::memory_order_seq_cst); // 2
}
void read_x_then_y()
{
while(!x.load(std::memory_order_seq_cst)); // 3
if(y.load(std::memory_order_seq_cst)) // 4
++z;
}
void read_y_then_x()
{
while(!y.load(std::memory_order_seq_cst)); // 5
if(x.load(std::memory_order_seq_cst)) // 6
++z;
}
int main() {
x=false;
y=false;
z=0;
std::thread a(write_x);
std::thread b(write_y);
std::thread c(read_x_then_y);
std::thread d(read_y_then_x);
a.join();
b.join();
c.join();
d.join();
assert(z.load()!=0);
}
Run Code Online (Sandbox Code Playgroud)
在《C++ Concurrency in Action》一书中,作者在谈论顺序一致性时给出了这个例子,并说assert永远不能触发,因为
[1] 或 [2] 必须首先发生...并且如果一个线程看到 x==true 然后随后看到 y==false,这意味着按照总顺序,对 x 的存储发生在对 y 的存储之前。
我知道所有顺序一致的原子操作存在一个全局总顺序,如果一个线程看到 x == true,则意味着操作 1 与操作 3 同步,并且也在操作 3 之前发生,但我的问题是该线程是否随后看到 y == false,为什么它意味着1发生在2之前?是否有可能操作 2 在操作 1 之前发生,但操作 4 没有看到该值发生变化?
是否有可能操作 2 在操作 1 之前发生,但操作 4 没有看到该值发生变化?
请务必注意此处的术语。您在这里所说的“发生之前”并不是内存模型描述中使用的发生之前关系。您在这里的意思是在顺序一致操作的总顺序中发生在之前。
假设我们写的X < Y意思是,按照总顺序,操作X发生在操作之前。Y你考虑一下情况2 < 1。为了4观察存储之前的值,我们还需要4 < 2. 还有一个条件是3观察存储的值,否则4永远不会达到,所以也1 < 3。最后我们有3是sequence-before 的4并且总顺序必须与之一致,所以也是3 < 4。
总而言之:
2 < 1
4 < 2
1 < 3
3 < 4
Run Code Online (Sandbox Code Playgroud)
如果您现在尝试创建1, 2, 3, 4满足这些条件的全序,您会发现它不起作用。要证明这一点,请参阅2 < 1和1 < 3暗示2 < 3,其中 和3 < 4暗示2 < 4。这自相矛盾4 < 2。
不存在满足条件的全序,因此这不是可能的结果。必须看到商店之后的4价值,这实际上是我上面使用的连锁店推导出来的。(如果你仔细检查用上面的条件替换不会产生任何其他矛盾,所以你还可以找到一个真正满足所有条件的全序。)4 < 24 < 22 < 4