C++ 标准::原子| compare_exchange_weak 与 compare_exchange_strong
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/4944771/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
std::atomic | compare_exchange_weak vs. compare_exchange_strong
提问by 0xbadf00d
I'm unsure if it's me not understanding or the documentation isn't clearly formulated.
我不确定是我不理解还是文档没有明确表述。
The following excerpt has been taken from the newest draft (N3126, section 29.6):
以下摘录自最新草案(N3126,第 29.6 节):
bool atomic_compare_exchange_weak(volatile A* object, C * expected, C desired);
bool atomic_compare_exchange_weak(A* object, C * expected, C desired);
bool atomic_compare_exchange_strong(volatile A* object, C * expected, C desired);
bool atomic_compare_exchange_strong(A* object, C * expected, C desired);
bool atomic_compare_exchange_weak_explicit(volatile A* object, C * expected, C desired, memory_order success, memory_order failure);
bool atomic_compare_exchange_weak_explicit(A* object, C * expected, C desired, memory_order success, memory_order failure);
bool atomic_compare_exchange_strong_explicit(volatile A* object, C * expected, C desired, memory_order success, memory_order failure);
bool atomic_compare_exchange_strong_explicit(A* object, C * expected, C desired, memory_order success, memory_order failure);
bool A::compare_exchange_weak(C & expected, C desired, memory_order success, memory_order failure) volatile;
bool A::compare_exchange_weak(C & expected, C desired, memory_order success, memory_order failure);
bool A::compare_exchange_strong(C & expected, C desired, memory_order success, memory_order failure) volatile;
bool A::compare_exchange_strong(C & expected, C desired, memory_order success, memory_order failure);
bool A::compare_exchange_weak(C & expected, C desired, memory_order order = memory_order_seq_cst) volatile;
bool A::compare_exchange_weak(C & expected, C desired, memory_order order = memory_order_seq_cst);
bool A::compare_exchange_strong(C & expected, C desired, memory_order order = memory_order_seq_cst) volatile;
bool A::compare_exchange_strong(C & expected, C desired, memory_order order = memory_order_seq_cst);
Remark: The weak compare-and-exchange operations may fail spuriously, that is, return false while leaving the contents of memory pointed to by expected before the operation is the same that same as that of the object and the same as that of expected after the operation. [ Note: This spurious failure enables implementation of compare-and-exchange on a broader class of machines, e.g., loadlocked store-conditional machines. A consequence of spurious failure is that nearly all uses of weak compare-and-exchange will be in a loop.
备注:弱比较和交换操作可能会虚假失败,即返回false而操作之前expected指向的内存内容与对象相同,之后与expected相同操作。[注意:这种虚假故障可以在更广泛的机器类别上实现比较和交换,例如,负载锁定的存储条件机器。虚假失败的结果是几乎所有弱比较和交换的使用都将处于循环中。
So, what does this mean?
那么这是什么意思?
Firstly, it 'may' fail spuriously?! Why would it fail? And how do they define 'may'?
首先,它“可能”错误地失败?!为什么会失败?他们如何定义“可能”?
Secondly, I still have no idea what's the difference between the functions with "_strong" and "_weak" suffix. Could someone explain the difference?
其次,我仍然不知道带有“_strong”和“_weak”后缀的函数之间有什么区别。有人能解释一下区别吗?
EDIT:That's what I've found in libstdc++-implementation (atomic_0.h):
编辑:这就是我在 libstdc++-implementation (atomic_0.h) 中发现的:
bool compare_exchange_weak(
__integral_type& __i1,
__integral_type __i2,
memory_order __m1,
memory_order __m2
)
{
__glibcxx_assert(__m2 != memory_order_release);
__glibcxx_assert(__m2 != memory_order_acq_rel);
__glibcxx_assert(__m2 <= __m1);
return _ATOMIC_CMPEXCHNG_(this, &__i1, __i2, __m1);
}
bool compare_exchange_strong(
__integral_type& __i1,
__integral_type __i2,
memory_order __m1,
memory_order __m2
)
{
__glibcxx_assert(__m2 != memory_order_release);
__glibcxx_assert(__m2 != memory_order_acq_rel);
__glibcxx_assert(__m2 <= __m1);
return _ATOMIC_CMPEXCHNG_(this, &__i1, __i2, __m1);
}
采纳答案by janneb
It has to do with the shared memory consistency model that the hardware implements. For those hardware architectures that implement some kind of relaxed consistency model (e.g. release semantics), the strong operations you refer to above can have a high overhead, and thus experts can use the weaker forms to implement algorithms that perform well also on those relaxed consistency architectures.
它与硬件实现的共享内存一致性模型有关。对于那些实现某种宽松一致性模型(例如发布语义)的硬件架构,您在上面提到的强操作可能具有很高的开销,因此专家可以使用较弱的形式来实现在这些宽松一致性上也表现良好的算法架构。
For more info, see e.g.
有关更多信息,请参见例如
http://www.hpl.hp.com/techreports/Compaq-DEC/WRL-95-7.pdf
http://www.hpl.hp.com/techreports/Compaq-DEC/WRL-95-7.pdf
Chapter 12 and Appendix C in http://kernel.org/pub/linux/kernel/people/paulmck/perfbook/perfbook.html
http://kernel.org/pub/linux/kernel/people/paulmck/perfbook/perfbook.html 中的第 12 章和附录 C
回答by Jonathan Wakely
The note gives a clue, referring to LL/SCarchitectures. From the Wikipedia article:
该注释提供了一个线索,指的是LL/SC架构。来自维基百科文章:
If any updates have occurred, the store-conditional is guaranteed to fail, even if the value read by the load-link has since been restored. As such, an LL/SC pair is stronger than a read followed by a compare-and-swap (CAS), which will not detect updates if the old value has been restored (see ABA problem).
Real implementations of LL/SC do not always succeed if there are no concurrent updates to the memory location in question. Any exceptional events between the two operations, such as a context switch, another load-link, or even (on many platforms) another load or store operation, will cause the store-conditional to spuriously fail.
如果发生了任何更新,即使加载链接读取的值已经恢复,也保证条件存储失败。因此,LL/SC 对强于读取后跟比较和交换 (CAS),如果旧值已恢复,则不会检测更新(请参阅 ABA 问题)。
如果没有对相关内存位置进行并发更新,LL/SC 的实际实现并不总是成功。两个操作之间的任何异常事件,例如上下文切换、另一个加载链接,甚至(在许多平台上)另一个加载或存储操作,都会导致 store-conditional 虚假失败。
On LL/SC chips the compare_exchange
will be implemented in terms of LL/SC, which can spuriously fail, so compare_exchange_strong
needs extra overhead to retry in the case of failure. Providing both compare_exchange_strong
and compare_exchange_weak
allows the programmer to decide whether they want the library to handle spurious failures (in which case they'd use compare_exchange_strong
or if they want to handle it in their own code (in which case they'd use compare_exchange_weak
)
在 LL/SC 芯片上,compare_exchange
将根据 LL/SC 实现,这可能会虚假失败,因此compare_exchange_strong
在失败的情况下需要额外的开销来重试。提供两者compare_exchange_strong
并compare_exchange_weak
允许程序员决定他们是否希望库处理虚假故障(在这种情况下他们会使用,compare_exchange_strong
或者他们是否想在自己的代码中处理它(在这种情况下他们会使用compare_exchange_weak
)