Когда мне действительно нужно использовать atom <bool> вместо bool?

Является ли atomic<bool> избыточным, потому что bool является атомарным по своей природе? Я не думаю, что возможно иметь частично измененное значение bool. Когда мне действительно нужно использовать atomic<bool> вместо bool?

Ответ 1

Ни один тип в С++ не является "атомарным по своей природе", если он не является std::atomic* -something. Это потому, что стандарт так говорит.

На практике фактические аппаратные команды, которые испускаются для управления std::atomic<bool>, могут (или не могут) быть такими же, как и для обычного bool, но быть атомарным - это более крупная концепция с более широкими последствиями (например, ограничения при переупорядочении компилятора). Кроме того, некоторые операции (например, отрицание) перегружены на атомарной операции для создания явно отличающейся команды на аппаратном обеспечении, чем нативная, неатомная последовательность чтения-модификации-записи неатомной переменной.

Ответ 2

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

Ответ 3

Атомные типы С++ связаны с потенциальными проблемами трех. Во-первых, чтение или запись может быть разорвано переключателем задачи, если для операции требуется более одной операции с шиной (и может bool, в зависимости от того, как она реализована). Во-вторых, чтение или запись могут влиять только на кеш, связанный с процессором, выполняющим операцию, а другие процессоры могут иметь другое значение в своем кеше. В-третьих, компилятор может изменить порядок операций, если они не влияют на результат (ограничения немного сложнее, но этого достаточно на данный момент).

Вы можете справиться с каждой из этих трех проблем самостоятельно, сделав предположения о том, как реализуются типы, которые вы используете, путем явного промывания кешей и с помощью специальных параметров для компилятора, чтобы предотвратить переупорядочение (и, нет, volatile не делает этого, если в вашей документации по компилятору это не говорится).

Но зачем все это переживать? atomic заботится об этом для вас и, вероятно, делает лучшую работу, чем вы можете сделать самостоятельно.

Ответ 4

Атомные операции - это больше, чем просто порванные ценности, поэтому, хотя я согласен с вами и другими плакатами, что я не знаю об окружающей среде, где разрыв bool возможен, на карту поставлено больше.

Трава Саттер рассказала об этом, который вы можете посмотреть онлайн. Будьте предупреждены, это долгая беседа. Herb Sutter, Atomic Weapons. Проблема сводится к тому, чтобы избежать гонок данных, потому что это позволяет вам иметь иллюзию последовательной согласованности.

Ответ 5

Рассмотрим операцию сравнения и обмена:

bool a = ...;
bool b = ...;

if (a)
    swap(a,b);

После того, как мы прочитаем a, мы получим true, другой поток может прийти и установить ложь, затем мы заменим (a, b), поэтому после выхода b будет false, даже если был сделан обмен.

Используя std::atomic::compare_exchange, мы можем сделать всю логику if/swap атомарно так, чтобы другой поток не мог установить значение false в значение между if и swap (без блокировки). В таком случае, если смена была сделана, а b должна быть ложной при выходе.

Это всего лишь один пример атомной операции, которая применяется к двум типам значений, таким как bool.

Ответ 6

Атоматичность определенных типов зависит исключительно от базового оборудования. Каждая архитектура процессора имеет разные гарантии относительно атомарности определенных операций. Например:

Процессор Intel486 (и более новые процессоры с тех пор) гарантирует, что следующие основные операции с памятью всегда будут выполняться атомарно:

  • Чтение или запись байта
  • Чтение или запись слова, выровненного на 16-битной границе
  • Чтение или запись двойного слова, выровненного на 32-битной границе

Другие архитектуры имеют разные спецификации, по которым операции являются атомарными.

С++ - это высокоуровневый язык программирования, который стремится отвлечь вас от базового оборудования. По этой причине стандарт просто не может позволить полагаться на такие допущения на низком уровне, потому что в противном случае ваше приложение не будет переносимым. Соответственно, все примитивные типы в С++ снабжаются atomic аналогами стандартной совместимой с С++ 11 стандартной библиотекой.