#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:
- x 设为真
- 在(4)处,y.load返回false,z保持为零
- y 设为真
- (6)后z变成1
案例 B:
- y 设为真
- 在(6)处,x.load返回false,z保持为零
- x 设为真
- (4)后z变成1
案例 C:
- x 设为真,y 设为真
- 经过(4)和(6)后,z变为2
我不能保证x
或 y
将首先设置为真,但是当x
设置为真,加载x
应该与它同步以及y,
那么什么样的情况会使z
保持零?
最佳答案
这正是 Anthony Williams 的“Concurrency In Action”中的示例 list 5.7。
他解释说:
In this case the assert can fire (just like in the relaxed-ordering case), because it’s possible for both the load of
x
and the load ofy
to readfalse
. x and y are written by different threads, so the ordering from the release to the acquire in each case has no effect on the operations in the other threads.
关于c++ - c++11(atomic)的获取释放操作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18677139/