std :: atomic | compare_exchange_weak与compare_exchange_strong

0xb*_*00d 28 c++ stl atomic c++-standard-library c++11

我不确定我是不理解还是文件没有明确制定.

以下摘录摘自最新草案(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);
Run Code Online (Sandbox Code Playgroud)

备注:弱比较和交换操作可能会失败,即返回false,同时在操作与对象的操作相同且与预期之后相同的情况下保留预期指向的内存内容操作.[注意:这种虚假故障可以在更广泛的机器类上实现比较和交换,例如,加载锁定的存储条件机器.虚假失败的后果是几乎所有弱比较和交换的使用都将处于循环中.

那么这是什么意思?

首先,它'可能'虚假失败?!为什么会失败?他们如何定义'可能'?

其次,我仍然不知道具有"_strong"和"_weak"后缀的函数之间的区别是什么.有人可以解释这个区别吗?

编辑: 这就是我在libstdc ++中发现的 - 实现(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);
}
Run Code Online (Sandbox Code Playgroud)

Jon*_*ely 33

该注释提供了线索,指的是LL/SC架构.来自维基百科的文章:

如果发生任何更新,即使已经恢复了load-link读取的值,store-conditional也会失败.因此,LL/SC对比读取后跟比较和交换(CAS)更强,如果旧值已经恢复,则不会检测更新(参见ABA问题).

如果没有对所讨论的存储器位置进行并发更新,则LL/SC的实际实现并不总是成功.两个操作之间的任何异常事件(例如上下文切换,另一个加载链接,或甚至(在许多平台上)另一个加载或存储操作)将导致存储条件虚假地失败.

在LL/SC芯片上,compare_exchange将以LL/SC的形式实现,这可能是虚假的失败,因此compare_exchange_strong在发生故障时需要额外的开销来重试.提供两者compare_exchange_strongcompare_exchange_weak允许程序员决定他们是否希望库处理虚假故障(在这种情况下,他们使用compare_exchange_strong或者如果他们想要在他们自己的代码中处理它(在这种情况下他们会使用compare_exchange_weak)

  • @CygnusX1 是的,注释的其余部分在 C++ 标准中涵盖了这一点,OP 省略了引用:“当比较和交换处于循环中时,弱版本将在某些平台上产生更好的性能。当弱比较和交换需要循环而强比较和交换不需要循环时,强比较和交换是更好的选择。” 推论是,当你无论如何都要循环时,没有理由选择强循环。 (2认同)

jan*_*neb 11

它与硬件实现的共享内存一致性模型有关.对于那些实现某种宽松一致性模型(例如发布语义)的硬件体系结构,您在上面提到的强大操作可能会产生很高的开销,因此专家可以使用较弱的表单来实现那些在那些宽松的一致性上表现良好的算法架构.

有关详细信息,请参阅例如

http://www.hpl.hp.com/techreports/Compaq-DEC/WRL-95-7.pdf

http://kernel.org/pub/linux/kernel/people/paulmck/perfbook/perfbook.html中的第12章和附录C

  • @FrEEzE:差异正是标准所说的 - 弱版本允许偶尔失败,如果这使得它在硬件上运行得更快.不适用于x86. (5认同)
  • 但是,难道不是memory_order参数的意义加强或削弱了内存排序模型吗? (2认同)