看下面代码:
#include <iostream>
#include <thread>
#include <assert.h>
#include <atomic>
int a = 0;
std::atomic<bool> flag{ false };
void f1()
{
a = 1;
flag.store(true, std::memory_order_release);
//flag.store(true, std::memory_order_relaxed);
}
void f2()
{
while (!flag.load(std::memory_order_acquire))
//while (!flag.load(std::memory_order_relaxed))
{
}
assert(a == 1);
}
int main(void)
{
std::thread t2(f2);
std::thread t1(f1);
t1.join();
t2.join();
return 0;
}
1 memory_order_release要求,在调用memory_order_release之前的所有写操作,不得重排到memory_order_release之后。在上面的代码里,显然a = 1就是写入。
2 memory_order_acquire要求,在调用memory_order_acquire之后的所有读操作,不得重排到memory_order_acquire之前。在上面的代码里,a == 1是对a当前值的判断,当然属于读操作。
3 结合1与2,函数f2的while循环直到flag == true才会跳出,所以跳出之前,f1一定已经将flag.store执行完毕了。那么根据(1)的要求,a=1的操作肯定发生在flag.store之前。于是,while()循环结束后,a=1的操作一定已经发生了。再结合上一篇理解原子变量之四:可见性、memory_order_acquire与 memory_order_release_memory order acquire-CSDN博客的可见性,a的改变一定可以对此时的线程t2可见。
最后,根据(2)的要求,assert(a == 1)一定发生在while之后,因为里面含有flag.load(memory_order_acquire)。所以assert(a == 1)一定可以看到a == 1为真。
最后,建议读一下微信公众号“程序喵大人”的文章《【C++并发系列】第五章:C++ 内存模型在约束什么?》,里面的描述更加全面。

315

被折叠的 条评论
为什么被折叠?



