相关疑难解决方法(0)

C++内存模型中的哪些确切规则会阻止在获取操作之前重新排序?

我在以下代码中有关于操作顺序的问题:

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在跑步thread1thread2同时之后永远不会有结果.

但是,我在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以及 …

c++ atomic memory-barriers language-lawyer stdatomic

18
推荐指数
2
解决办法
780
查看次数

C++20:标准如何保证atomic::wait()的返回?

这是一个语言律师问题。

\n

首先,a.wait()下面的代码是否总是返回?

\n
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}\n
Run Code Online (Sandbox Code Playgroud)\n

我相信标准的目的是a.wait()总是得到回报。(否则atomic::wait/notify就没用了,不是吗?)但我认为目前的标准文本不能保证这一点。

\n

标准的相关部分位于 \xc2\xa731.6 [atomics.wait] 第 4 段:

\n
\n

对原子对象上的原子等待操作的调用M可以通过调用原子通知操作来解除阻塞M,如果存在副作用X,并且Y满足M以下条件:

\n
    \n
  • (4.1) \xe2\x80\x94 观察结果后,原子等待操作已阻塞X
  • \n
  • (4.2) \xe2\x80\x94在,的修改顺序X之前YM
  • \n
  • (4.3) \xe2\x80\x94Y发生在调用原子通知操作之前。
  • \n
\n
\n

和 \xc2\xa731.8.2 [atomics.types.operations] 第 29~33 段:

\n
\n

void wait(T …

c++ atomic language-lawyer stdatomic c++20

13
推荐指数
1
解决办法
1341
查看次数