#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,那么加载和存储在同一个原子变量上的操作将同步,但这个简单的示例并不像我预期的那样工作。
这个过程是基于我的想象
1. x set as true
2. at (4), y.load return false, z remain zero
3. y set as true
4. after (6), z become one
1. y set as true
2. at (6), x.load return false, z remain zero
3. x set as true
4. after (4), z become one
1. x set as true, y set as true
2. after (4) and (6), z become 2
我不能保证首先将x或y设置为true,但是当x设置为true时,x的负载应该与它以及y,同步,那么什么样的情况会使z保持为零呢?
发布于 2013-09-07 19:57:16
这就是,,来自安东尼·威廉姆斯的“并发性在行动中”的示例清单5.7。
他解释说:
在这种情况下,断言可以触发(就像轻松排序的情况一样),因为
x的加载和y的加载都可以读取false。x和y是由不同的线程编写的,因此从发布到获取的顺序在每种情况下都不会对其他线程中的操作产生影响。

发布于 2013-09-08 07:37:17
除非使用seq_cst,否则C/C++11不能保证存储到不同内存位置的总顺序。因此,每个线程都可以自由地按不同的顺序查看存储。获取-发布同步没有帮助,因为它只是从执行存储的线程到执行加载的线程。如果你想玩这样的单元测试,并更好地发展你的直觉,试试CDSChecker。它是一个工具,它将向您展示C11的任何实际实现可能产生的所有行为。
https://stackoverflow.com/questions/18677139
复制相似问题