我在以下代码中有关于操作顺序的问题:
std::atomic<int> x;
std::atomic<int> y;
int r1;
int r2;
void thread1() {
y.exchange(1, std::memory_order_acq_rel);
r1 = x.load(std::memory_order_relaxed);
}
void thread2() {
x.exchange(1, std::memory_order_acq_rel);
r2 = y.load(std::memory_order_relaxed);
}
Run Code Online (Sandbox Code Playgroud)
鉴于std::memory_order_acquirecppreference页面上的描述(https://en.cppreference.com/w/cpp/atomic/memory_order),
具有此内存顺序的加载操作会对受影响的内存位置执行获取操作:在此加载之前,不能对当前线程中的读取或写入进行重新排序.
很明显,r1 == 0 && r2 == 0在跑步thread1和thread2同时之后永远不会有结果.
但是,我在C++标准中找不到任何措辞(现在查看C++ 14草案),这保证了两个宽松的加载不能与获取 - 释放交换重新排序.我错过了什么?
编辑:正如评论中所建议的那样,实际上可以使r1和r2都等于零.我已经更新了程序以使用load-acquire,如下所示:
std::atomic<int> x;
std::atomic<int> y;
int r1;
int r2;
void thread1() {
y.exchange(1, std::memory_order_acq_rel);
r1 = x.load(std::memory_order_acquire);
}
void thread2() {
x.exchange(1, std::memory_order_acq_rel);
r2 = y.load(std::memory_order_acquire);
}
Run Code Online (Sandbox Code Playgroud)
现在是有可能得到两个和r1以及 …
这是一个语言律师问题。
\n首先,a.wait()下面的代码是否总是返回?
std::atomic_int a{ 0 };\n\nvoid f()\n{\n a.store(1, std::memory_order_relaxed);\n a.notify_one();\n}\nint main()\n{\n std::thread thread(f);\n\n a.wait(0, std::memory_order_relaxed);//always return?\n\n thread.join();\n}\nRun Code Online (Sandbox Code Playgroud)\n我相信标准的目的是a.wait()总是得到回报。(否则atomic::wait/notify就没用了,不是吗?)但我认为目前的标准文本不能保证这一点。
标准的相关部分位于 \xc2\xa731.6 [atomics.wait] 第 4 段:
\n\n\n对原子对象上的原子等待操作的调用
\nM可以通过调用原子通知操作来解除阻塞M,如果存在副作用X,并且Y满足M以下条件:\n
\n- (4.1) \xe2\x80\x94 观察结果后,原子等待操作已阻塞
\nX,- (4.2) \xe2\x80\x94在,的修改顺序
\nX之前YM- (4.3) \xe2\x80\x94
\nY发生在调用原子通知操作之前。
和 \xc2\xa731.8.2 [atomics.types.operations] 第 29~33 段:
\n\n
void wait(T …