bool compare_exchange_weak (T& expected, T val, ..);
compare_exchange_weak()
是C ++ 11中提供的比较交换原语之一。即使对象的值等于,它也返回false,这是弱的expected
。这是由于在某些平台上使用了一系列指令(而不是x86上的指令)来实现它的虚假故障所致。在这样的平台上,上下文切换,另一个线程重新加载相同的地址(或缓存行)等可能会使原语失败。这是spurious
因为它不是所述对象(不等于的值expected
失败的操作)。相反,这是一种时间问题。
但令我感到困惑的是C ++ 11标准(ISO / IEC 14882)中所说的内容,
29.6.5 ..伪失败的后果是几乎所有弱比较和交换的使用都将循环。
为什么几乎在所有用途中它都必须处于循环状态?这是否意味着我们会在由于虚假故障而失败时循环?如果是这样,为什么我们还要compare_exchange_weak()
自己动手使用和编写循环?我们可以使用compare_exchange_strong()
我认为应该为我们消除虚假故障的方法。常见的用例是compare_exchange_weak()
什么?
另一个问题有关。安东尼在他的《行动中的C ++并发性》一书中说:
//Because compare_exchange_weak() can fail spuriously, it must typically
//be used in a loop:
bool expected=false;
extern atomic<bool> b; // set somewhere else
while(!b.compare_exchange_weak(expected,true) && !expected);
//In this case, you keep looping as long as expected is still false,
//indicating that the compare_exchange_weak() call failed spuriously.
为什么!expected
在循环条件下?是否在这里防止所有线程都饿死并且一段时间没有进步?
编辑:(最后一个问题)
在没有单个硬件CAS指令的平台上,弱版本和强版本都使用LL / SC(例如ARM,PowerPC等)实现。那么以下两个循环之间有什么区别吗?为什么,如果有的话?(对我来说,它们应该具有相似的性能。)
// use LL/SC (or CAS on x86) and ignore/loop on spurious failures
while (!compare_exchange_weak(..))
{ .. }
// use LL/SC (or CAS on x86) and ignore/loop on spurious failures
while (!compare_exchange_strong(..))
{ .. }
我提到了最后一个问题,你们都提到循环中可能存在性能差异。C ++ 11标准(ISO / IEC 14882)也提到了这一点:
当比较和交换处于循环中时,弱版本将在某些平台上产生更好的性能。
但如上所述,循环中的两个版本应具有相同/相似的性能。我想念什么?