#include <atomic>
#include <iostream>
#include <thread>
class atomicAcquireRelease00
{
public:
atomicAcquireRelease00() : x(false), y(false), z(0) {}
void run()
{
std::thread a(&atomicAcquireRelease00::write_x, this);
std::thread b(&atomicAcquireRelease00::write_y, this);
std::thread c(&atomicAcquireRelease00::read_x_then_y, this);
std::thread d(&atomicAcquireRelease00::read_y_then_x, this);
a.join();
b.join();
c.join();
d.join();
std::cout<<"z == "<<z.load()<<std::endl;
}
private:
void write_x()
{
x.store(true, std::memory_order_release); //(1)
}
void write_y()
{
y.store(true, std::memory_order_release); //(2)
}
void read_x_then_y()
{
while(!x.load(std::memory_order_acquire)); //(3)
if(y.load(std::memory_order_acquire)){ //(4)
++z;
}
}
void read_y_then_x()
{
while(!y.load(std::memory_order_acquire)); //(5)
if(x.load(std::memory_order_acquire)){ //(6)
++z;
}
}
private:
std::atomic<bool> x, y;
std::atomic<int> z;
};
int main()
{
for(size_t i = 0; i != 50; ++i){
atomicAcquireRelease00().run();
}
return 0;
}
atomicAcquireRelease00
在加载值时不尊重订单。如
如我所知,如果我将操作商店声明为std::memory_order_release
和操作加载为std::memory_order_acquire
作为一对,操作
加载和存储在同一个原子变量上会同步,但这很简单
示例不能像我预期的那样工作。
这个过程基于我的想象力
案例A:
案例B:
案例C:
我无法保证x
或y
首先设置为true,但当x
设置为true时,x
的加载应与其同步以及y,
那么什么样的情况会使z
保持为零?
答案 0 :(得分:9)
完全 来自Anthony Williams的“并发行动”中的示例清单5.7。
他解释道:
在这种情况下,断言可以触发(就像在宽松排序的情况下一样),因为
x
的加载和y
的加载都可能阅读false
。 x和y由不同的线程写入,因此在每种情况下从发布到获取的排序对其他线程中的操作没有影响。
答案 1 :(得分:2)
除非您使用seq_cst,否则C / C ++ 11不保证商店到不同内存位置的总顺序。因此,每个线程都可以以不同的顺序自由查看商店。获取 - 释放同步没有帮助,因为它只是从执行存储的线程到执行加载的线程。 如果你想玩这样的单元测试并更好地发展你的直觉,试试CDSChecker。它是一个工具,可以向您显示C11的任何实际实现可能产生的所有行为。