[B] но как определение as как std :: atomic делает эти множественные транзакции атомарными?
Это не делает атомарные «множественные транзакции» в произвольном выражении (например, это не поможет в вашем a = a + 1
примере).Скорее, вам нужно использовать операцию типа a++
, которая гарантированно будет атомарной.В этом случае способ его реализации зависит от компилятора и аппаратного обеспечения, но наиболее распространенными являются следующие стратегии:
- Используется одна инструкция атомарная операция , которая может автоматически увеличиватьзначение в памяти.На x86 это будет что-то вроде инструкция
lock add
. - Некоторый тип сравнения и обмена (CAS) или с нагрузкойЦепочка условного хранения (LL-SC) используется для многократной попытки сделать приращение атомарным способом.Вы можете увидеть LL-SC в действии на MIPS64.
- Наконец, на платформах, которые не поддерживают такие операции, или где тип данных несовместим с этими инструкциями, можно получить блокировкуисключить любой параллельный доступ при выполнении операции с обычными неатомарными инструкциями.Большинству основных платформ не нужно прибегать к этому для атомарных типов, но вы все еще можете увидеть пример здесь на старом компиляторе ARM.
Вы можете проверитьповедение вашей комбинации компилятора и аппаратного обеспечения путем изучения сгенерированной сборки.Иногда это сложно, потому что компилятор может вызвать функцию, реализованную в библиотеке времени выполнения, и в этом случае вам придется проверить исходный код или дизассемблирование для этой функции.Это означает, что один и тот же двоичный файл может иметь разные реализации для атомарных операций на разных хостах, если реализация библиотеки времени выполнения отличается!
Если компилятор всегда может создавать подобный код, почему бы не всегда делать это?
Компилятор не всегда генерирует их, потому что они дорого стоят на аппаратном уровне.Например, обычное (неатомарное) сложение обычно занимает 1 цикл или меньше 2 на большинстве современных процессоров 1 , в то время как атомарное сложение может занимать от 15 до 100 циклов.Подходы, использующие CAS или LL-SC, как правило, еще медленнее и требуют повторных циклов, увеличивая размер двоичного файла.
1 Возможно, до нескольких циклов на некоторых микроконтроллерахклассовые процессоры - но там атомарные операции часто менее актуальны, так как может не быть нескольких ядер.
2 Зависит от того, как вы его измеряете - сложение обычно занимает один цикл до завершения (задержка), но вы часто можете выполнить более одного независимого дополнения в одном цикле.Например, современные процессоры Intel могут выполнять четыре за один цикл.