Почему переменная volatile используется через out std::atomic?
Из того, что я прочитал от Херба Саттера и других, вы могли подумать, что volatile
и параллельное программирование было полностью ортогональными понятиями, по крайней мере, в том, что касается C/C++.
Однако в реализации GCC все std::atomic
функции-члены имеют volatile
Классификатор. То же самое верно в реализации Энтони Уильямса std::atomic
,
Так в чем же дело, сделай мой atomic<>
переменные должны быть volatile
или нет?
3 ответа
Почему volatile
квалификатор используется во всем std::atomic
?
Так что летучие объекты также могут быть атомными. Смотрите здесь:
Соответствующая цитата
Функции и операции определены для работы с изменчивыми объектами, так что переменные, которые должны быть изменчивыми, также могут быть атомарными. Однако изменчивый квалификатор не требуется для атомарности.
Сделать мой atomic<>
переменные должны быть volatile
или нет?
Нет, атомные объекты не должны быть летучими.
Подводя итог, что правильно написали другие:
C / C++ volatile
для аппаратного доступа и прерываний. C++11 atomic<>
предназначен для связи между потоками (например, в коде без блокировки). Эти два понятия / использования являются ортогональными, но у них есть частично совпадающие требования, и именно поэтому люди часто путают их.
Причина того, что atomic<>
имеет функции с квалификацией volatile по той же причине, что и функции с квалификацией const, потому что в принципе возможно, что объект atomic<>
а также const
и / или volatile
,
Конечно, как указывалось в моей статье, еще одним источником путаницы является то, что C / C++ volatile
не то же самое, что C# / Java volatile
(последнее в основном эквивалентно C++ 11 atomic<>
).
Как const, volatile является переходным. Если вы объявите метод как volatile
тогда вы не можете вызвать какой-либо энергонезависимый метод для него или любого из его атрибутов-членов. Имея std::atomic
методы volatile
вы разрешаете звонки из volatile
методы-члены в классах, которые содержат std::atomic
переменные.
У меня нет хорошего дня... так запутанно... может быть, небольшой пример помогает:
struct element {
void op1() volatile;
void op2();
};
struct container {
void foo() volatile {
e.op1(); // correct
//e.op2(); // compile time error
}
element e;
};