Когда следует использовать std:: atomic compare exchange strong?
В C++11 есть две атомарные операции CAS:atomic_compare_exchange_weak
и atomic_compare_exchange_strong
.
По данным cppreference:
слабые формы функций позволены потерпеть неудачу spuriously, то есть, действуйте как будто * obj != *ожидается, даже если они равны. Когда compare-and-exchange находится в цикле, слабая версия даст лучше производительность на некоторых платформах. когда слабый compare-and-exchange будет требуется петля и сильная нет, сильный предпочтительнее!--12-->.
пример использования слабый версия, мне кажется:
do {
expected = current.value();
desired = f(expected);
} while (!current.atomic_compare_exchange_weak(expected, desired));
может ли кто-нибудь привести пример, когда сравнение и обмен не находятся в цикле, так что сильный версия предпочтительнее?
1 ответов
на atomic_compare_exchange_XXX
функции обновляют свой" ожидаемый " аргумент с наблюдаемым значением, поэтому ваш цикл такой же, как:
expected = current;
do {
desired = f(expected);
} while (!current.atomic_compare_exchange_weak(expected, desired));
если требуемое значение независимая ожидаемого значения, этот цикл становится:
desired = ...;
expected = current;
while (current.atomic_compare_exchange_weak(expected, desired))
;
давайте добавим некоторую семантику. Предположим, что несколько потоков работают одновременно. В каждом случае desired
является ненулевым идентификатором для текущего потока и current
используется для обеспечения взаимного исключения, чтобы гарантировать, что некоторые поток выполняет задачу очистки. Нам все равно, какой из них, но мы хотим быть уверены, что какой-то поток получает доступ (и, возможно, другие потоки могут наблюдать за победителем, читая его ID из current
).
мы можем достичь желаемой семантики:
expected = 0;
if (current.atomic_compare_exchange_strong(expected, this_thread)) {
// I'm the winner
do_some_cleanup_thing();
current = 0;
} else {
std::cout << expected << " is the winner\n";
}
это случай, когда atomic_compare_exchange_weak
потребуется цикл для достижения того же эффекта, что и atomic_compare_exchange_strong
, так как возможны ложные сбои:
expected = 0;
while(!current.atomic_compare_exchange_weak(expected, this_thread)
&& expected == 0))
;
if (expected == this_thread) {
do_some_cleanup_thing();
current = 0;
} else {
std::cout << expected << " is the winner\n";
}
стандарт предполагает, что реализации могут обеспечить более эффективный код в этом случае для atomic_compare_exchange_strong
чем петля с ..._weak
(§29.6.5/25 [Атомикс.типы.оперативный.запрос.)]