Ответ 1
Краткосрочный и быстрый ответ: volatile
(почти) бесполезен для ассеничного, многопоточного программирования приложений. Он не обеспечивает никакой синхронизации, не создает забора памяти и не обеспечивает порядок выполнения операций. Он не делает операции атомарными. Это не делает ваш код волшебным потоком в безопасности. volatile
может быть единственным недопонятым средством во всех С++. См. this, this и это для получения дополнительной информации о volatile
С другой стороны, volatile
имеет некоторое использование, которое может быть не столь очевидным. Его можно использовать так же, как использовать const
, чтобы помочь компилятору показать вам, где вы можете ошибиться при доступе к некоторому совместно используемому ресурсу незащищенным способом. Это использование обсуждается Александреску в в этой статье. Тем не менее, в основном это используется система типа С++, которая часто рассматривается как средство и может вызывать Undefined Behavior.
volatile
был специально предназначен для использования при взаимодействии с аппаратными средствами памяти, обработчиками сигналов и командой машинного кода setjmp. Это делает volatile
непосредственно применимым к программированию на системном уровне, а не нормальному программированию на уровне приложений.
В стандарте С++ 2003 не говорится, что volatile
применяет любые семантики Acquire или Release для переменных. Фактически, стандарт полностью умалчивает обо всех вопросах многопоточности. Однако конкретные платформы применяют семантику Acquire и Release на переменных volatile
.
[Обновление для С++ 11]
Стандарт С++ 11 теперь подтверждает многопоточность непосредственно в модели памяти и lanuage и предоставляет библиотечные возможности для решения этой проблемы независимо от платформы. Однако семантика volatile
все еще не изменилась. volatile
по-прежнему не является механизмом синхронизации. Бьярне Страуструп говорит так же в TCPPPL4E:
Не используйте
volatile
, за исключением низкоуровневого кода, который напрямую работает с аппаратным обеспечением.Не предполагайте, что
volatile
имеет особое значение в модели памяти. Это не. Это не так - как на некоторых более поздних языках - механизм синхронизации. Чтобы получить синхронизацию, используйтеatomic
, amutex
илиcondition_variable
.
[/Окончательное обновление]
Вышеприведенное все относится к самому языку С++, как определено стандартом 2003 года (и теперь стандартом 2011 года). Однако некоторые конкретные платформы добавляют дополнительные функциональные возможности или ограничения для того, что делает volatile
. Например, в MSVC 2010 (по крайней мере) семантика Acquire and Release применима к определенным операциям с переменными volatile
. Из MSDN:
При оптимизации компилятор должен поддерживать порядок среди ссылок к изменчивым объектам, а также ссылки на другие глобальные объекты. В частности,
Запись в изменчивый объект (volatile write) имеет семантику Release; ссылка на глобальный или статический объект, который возникает перед записью в летучий объект в последовательности команд будет происходить до этого volatile записывается в скомпилированный двоичный файл.
Чтение изменчивого объекта (volatile read) имеет семантику Acquire; ссылка на глобальный или статический объект, который возникает после чтения после этого будет записана энергозависимая память в последовательности команд волатильное чтение в скомпилированном двоичном файле.
Однако вы можете принять к сведению тот факт, что если вы будете следовать приведенной выше ссылке, в комментариях будет высказано мнение о том, действительно ли в этом случае применяются семантика получения/выпуска.