Понимание std :: atomic :: compare_exchange_weak () в C ++ 11

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):

Когда сравнение и обмен находятся в цикле, слабая версия приведет к лучшей производительности на некоторых платформах.

Но, как было проанализировано выше, две версии в цикле должны давать одинаковую / аналогичную производительность. Что я скучаю?

Ответы на вопрос(4)

Ваш ответ на вопрос