Может ли операция чтения/записи bool быть не атомарной на x86?

Скажем, у нас есть два потока: один читает bool в цикле, а другой может переключать его в определенное время. Лично я думаю, что это должно быть атомарным, потому что sizeof(bool) в С++ - 1 байт, и вы не читаете/не записываете байты частично, но я хочу быть на 100% уверенным.

Итак, да или нет?

ИЗМЕНИТЬ

Также для справок в будущем применяется то же самое к int?

Ответ 1

Все зависит от того, что вы на самом деле подразумеваете под словом "атомный".

Вы имеете в виду, что "окончательное значение будет обновляться за один раз" (да, на x86, который определенно гарантирован для байтового значения - и любое правильно выровненное значение до 64 бит) или "если я установил это для true (или false), ни один другой поток не будет читать другое значение после того, как я его установил" (это не совсем такая уверенность - вам нужен префикс "блокировки", чтобы гарантировать это).

Ответ 2

Есть три отдельных вопроса, которые "атомарные" типы в адресе С++ 11:

  • разрыв: чтение или запись включает в себя несколько циклов шины, а переключатель потоков происходит в середине операции; это может привести к неправильным значениям.

  • Когерентность кеширования: запись из одного потока обновляет кеш процессора, но не обновляет глобальную память; чтение из другого потока считывает глобальную память и не видит обновленного значения в кэше другого процессора.

  • оптимизация компилятора: компилятор перемещает порядок чтения и записи в предположении, что значения не доступны из другого потока, что приводит к хаосу.

Использование std::atomic<bool> гарантирует правильное управление всеми тремя из этих проблем. Не используя std::atomic<bool>, вы угадываете, в лучшем случае, не переносимый код.

Ответ 3

x86 гарантирует только выравнивание по слову и запись размера слова. Он не гарантирует никаких других операций, если явно не атомарно. Плюс, конечно, вы должны убедить своего компилятора в самом деле выпустить соответствующие чтения и записи в первую очередь.