С атомом c дело в том, что только один оператор является атомом c.
Если вы напишите
std::atomic<int> i {20}
...
if (!--i)
...
Тогда только 1 поток введет оператор if.
Однако, если вы разделите изменение и тест, тогда другие потоки могут попасть в разрыв, и вы можете получить странные результаты:
std::atomic<int> i {20}
...
--i;
// other thread(s) can modify i just here
if (!i)
...
Конечно, вы можете разделить условие проверить декремент с помощью локальной переменной:
std::atomic<int> i {20}
...
int j=--i;
// other thread(s) can modify i just here
if (!j)
...
Все простые математические операции, как правило, эффективно поддерживаются для малых атомов в c ++
Для более сложных типов и выражений вам необходимо использовать методы-члены чтения / изменения / записи.
Они позволяют вам прочитать текущее значение, вычислить новое значение и затем вызвать compare_exchange_strong
или compare_exchange_weak
сказать "если значение не изменилось, затем сохранить мое новое значение, в противном случае дайте мне новое текущее значение "a atomi c операция. Вы можете вставить это в al oop и продолжать пересчитывать новое значение, пока вам не повезет, что ваш поток является единственным автором. Если не слишком много потоков, которые слишком часто пытаются изменить значение, это также достаточно эффективно.