C++ C++;11内存模型允许将松弛的原子负载提升出循环?

C++ C++;11内存模型允许将松弛的原子负载提升出循环?,c++,c++11,atomic,atomicity,C++,C++11,Atomic,Atomicity,考虑以下代码: #include <atomic> extern std::atomic<int> i; void f(void) { while (!i.load(std::memory_order_relaxed)) ; } 我看过一些讨论,但没有得出结论 编辑:这篇文章的前一个版本在循环中调用了一个外部函数 编辑2:出于动机:《高效Java》一书说HotSpot VM执行以下转换: while (!done) i++; 到 即使另一个

考虑以下代码:

#include <atomic>

extern std::atomic<int> i;

void f(void)
{
  while (!i.load(std::memory_order_relaxed))
      ;
}
我看过一些讨论,但没有得出结论

编辑:这篇文章的前一个版本在循环中调用了一个外部函数

编辑2:出于动机:《高效Java》一书说HotSpot VM执行以下转换:

while (!done)
    i++;


即使另一个线程同时更改done变量是完美定义的行为。

忘记released,也不能保证原子存储对不同线程中的原子负载可见。你能得到的最好的是规范性的鼓励(以及类似的措辞):

实现应该使原子存储对原子负载可见 在合理的时间内

…这不是一项要求

(C11在§7.11.3/16中具有相同的措辞)


由于提升负载会导致与未提升负载无法区分的行为,在未提升负载的情况下,存储永远不可见,并且后者符合要求,因此“如同”规则允许实现提升负载,而不考虑使用的内存顺序。

请选择一种语言。C和C++的答案不同。@ KeReksb11和C++ 11具有相同的内存模型。这在任何情况下都不是有效的C++。在C++中,没有<代码>原子> />代码或STATDCOMPUCTION.H./COD> > .M.M N1570,FN 156:“省略的控制表达式被非零常量所代替,这是一个常量表达式。”@ M.M为(;;)不是UB:省略的控制表达式被非零常量所代替,这是一个常量表达式。您是说原始代码可能会触发未定义的行为还是什么?没有UB,但内存模型无法保证无论您执行何种负载,该循环都会终止。一切都是QoI。即使使用易失性原子变量?@xvan也不行,因为它会阻止编译器提升负载,但存储的可视性仍然可以延迟任意时间。这似乎不能回答问题。我想我们都会同意,如果OP使用了
memory\u-order\u-seq\u-cst
,那么他的自旋锁就可以正常工作(也就是说,如果一个线程将
I
设置为
1
,那么下一个要唤醒的线程就必须看到更新)。OP的问题是,将其更改为
内存\u顺序\u released
是否会破坏自旋锁(通过允许编译器从循环中提升负载),或者它是否仍然需要工作,如果需要,原因是什么。FWIW,我的直觉与OP一致——它不应该起作用——但我也通过godbolt确认GCC在ARM/MIPS/PPC上实际上不起作用。
while (!done)
    i++;
if (!done)
    while (true)
        i++;