Многие разработчики думают, что
compare_exchange_weak — это просто облегчённая версия compare_exchange_strong. На самом деле у неё есть неочевидное поведение: она может вернуть false, даже если значение совпадает.🍿 Как это работает:
На некоторых архитектурах (ARM, PowerPC) атомарные операции реализованы через инструкции load-link/store-conditional (LL/SC). Процессор помечает адрес памяти при чтении и проверяет при записи — не изменился ли он.
Но вот проблема: между LL и SC может произойти spurious failure — ложный отказ. Это случается, если:
• Произошло переключение контекста
• Кеш-линия была вытеснена
• Другой процессор обратился к соседней памяти
std::atomic<int> counter{0};
int expected = 0;
// Может вернуть false, даже если counter == 0!
bool success = counter.compare_exchange_weak(expected, 1);✈️ На x86 такого нет — там используется инструкция CMPXCHG, которая атомарна на уровне железа. Но спецификация C++ допускает spurious failures для переносимости.
💡 Практический вывод:
Всегда используй compare_exchange_weak в цикле. Для однократных попыток бери compare_exchange_strong — она гарантирует, что false означает реальное несовпадение значений.
📍Навигация: Вакансии • Задачи • Собесы
Библиотека C/C++ разработчика
#под_капотом