Может ли операция чтения/записи bool быть не атомарной на x86?
Скажем, у нас есть два потока: один читает bool в цикле, а другой может переключать его в определенное время. Лично я думаю, что это должно быть атомарным, потому что sizeof(bool)
в С++ - 1 байт, и вы не читаете/не записываете байты частично, но я хочу быть на 100% уверенным.
Итак, да или нет?
ИЗМЕНИТЬ
Также для справок в будущем применяется то же самое к int
?
Ответы
Ответ 1
Все зависит от того, что вы на самом деле подразумеваете под словом "атомный".
Вы имеете в виду, что "окончательное значение будет обновляться за один раз" (да, на x86, который определенно гарантирован для байтового значения - и любое правильно выровненное значение до 64 бит) или "если я установил это для true (или false), ни один другой поток не будет читать другое значение после того, как я его установил" (это не совсем такая уверенность - вам нужен префикс "блокировки", чтобы гарантировать это).
Ответ 2
Есть три отдельных вопроса, которые "атомарные" типы в адресе С++ 11:
-
разрыв: чтение или запись включает в себя несколько циклов шины, а переключатель потоков происходит в середине операции; это может привести к неправильным значениям.
-
Когерентность кеширования: запись из одного потока обновляет кеш процессора, но не обновляет глобальную память; чтение из другого потока считывает глобальную память и не видит обновленного значения в кэше другого процессора.
-
оптимизация компилятора: компилятор перемещает порядок чтения и записи в предположении, что значения не доступны из другого потока, что приводит к хаосу.
Использование std::atomic<bool>
гарантирует правильное управление всеми тремя из этих проблем. Не используя std::atomic<bool>
, вы угадываете, в лучшем случае, не переносимый код.
Ответ 3
x86 гарантирует только выравнивание по слову и запись размера слова. Он не гарантирует никаких других операций, если явно не атомарно. Плюс, конечно, вы должны убедить своего компилятора в самом деле выпустить соответствующие чтения и записи в первую очередь.