请考虑以下代码:
#include <atomic>
extern std::atomic<int> i;
void f(void)
{
while (!i.load(std::memory_order_relaxed))
;
}
我正在寻找C ++ 11标准的引文,该标准说不允许编译器将循环转换为
if (!i.load(std::memory_order_relaxed)) {
while (1)
;
}
我见过一些讨论here,但没有结论。
编辑:这篇文章的先前版本在循环中称为extern函数。
编辑2 :有动力:“Effective Java”一书说HotSpot VM执行以下转换:
while (!done)
i++;
到
if (!done)
while (true)
i++;
尽管它是另一个线程的完美定义行为,可以同时更改完成变量。
答案 0 :(得分:2)
忘记放松,不能保证原子存储永远对另一个线程中的原子加载可见。你得到的最好的是[atomics.order]/12中的规范性鼓励(以及[intro.progress]/18中类似的措辞):
实现应该使原子库对原子载荷可见 在合理的时间内。
......这不是一项要求。
(C11在§7.11.3/ 16中的措辞相同)
由于提升负载导致行为无法与存储永远不可见的非提升负载区分开来,并且由于后者符合要求,因此as-if规则允许实现提升负载,而不管内存顺序如何使用