Введение
Ключевое слово, используемое в некоторых языках программирования для обозначения переменных.
В компьютерном программировании "volatile" (изменчивый) означает, что значение может изменяться со временем вне контроля некоторого кода. Изменчивость имеет последствия для соглашений о вызовах функций, а также влияет на то, как переменные хранятся, к ним осуществляется доступ и кэшируются. В языках программирования C, C++, C# и Java ключевое слово "volatile" указывает, что значение может измениться между различными обращениями, даже если оно не выглядит измененным. Это ключевое слово предотвращает оптимизацию компилятором последующих операций чтения или записи, что может привести к неправильному повторному использованию устаревшего значения или пропуску операций записи. Изменчивые значения возникают главным образом при аппаратном доступе (ввод-вывод с отображением в память), когда чтение или запись в память используется для связи с периферийными устройствами, а также в многопоточном программировании, когда другое потоком может быть изменено значение. Несмотря на то, что это распространенное ключевое слово, поведение "volatile" существенно различается в разных языках программирования и может быть легко неправильно понято. В C и C++ это квалификатор типа, как и "const", и является свойством типа. Кроме того, в C и C++ оно не работает в большинстве сценариев многопоточности, и такое использование не рекомендуется. В Java и C# это свойство переменной, указывающее, что объект, к которому привязана переменная, может изменяться, и предназначено специально для многопоточности. В языке программирования D существует отдельное ключевое слово для использования в многопоточном программировании, но ключевого слова "volatile" не существует.
C++11
Согласно стандарту ISO C++11, ключевое слово `volatile` предназначено исключительно для доступа к аппаратному обеспечению; не используйте его для межпоточной коммуникации. Для межпоточной коммуникации стандартная библиотека предоставляет шаблоны `std::atomic<T>`.
На Яве
В языке программирования Java также есть ключевое слово `volatile`, но оно используется для несколько иной цели. При применении к полю, модификатор `volatile` в Java обеспечивает следующие гарантии:
Во всех версиях Java существует глобальный порядок чтения и записи всех переменных, объявленных как `volatile` (этот глобальный порядок для `volatile` является частичным порядком относительно более широкого порядка синхронизации, который является полным порядком для всех операций синхронизации). Это означает, что каждый поток, обращающийся к `volatile`-полю, будет читать его текущее значение, прежде чем продолжить, а не (возможно) использовать кэшированное значение. (Однако нет гарантий относительно порядка операций чтения и записи `volatile` по отношению к обычным операциям чтения и записи, что означает, что это, как правило, не является полезной конструкцией для многопоточности.) Начиная с Java 5, операции чтения и записи `volatile` устанавливают отношение "происходит-перед" (happens-before), аналогично захвату и освобождению мьютекса. Использование `volatile` может быть быстрее, чем использование блокировки, но оно может не работать в некоторых ситуациях в версиях Java до 5. Диапазон ситуаций, в которых `volatile` эффективно, был расширен в Java 5; в частности, двойная проверка блокировки теперь работает корректно.
In all versions of Java, there is a global ordering on reads and writes of all volatile variables (this global ordering on volatiles is a partial order over the larger synchronization order (which is a total order over all synchronization actions)). This implies that every thread accessing a volatile field will read its current value before continuing, instead of (potentially) using a cached value. (However, there is no guarantee about the relative ordering of volatile reads and writes with regular reads and writes, meaning that it's generally not a useful threading construct.) In Java 5 or later, volatile reads and writes establish a happens before relationship, much like acquiring and releasing a mutex. Using volatile may be faster than a lock, but it will not work in some situations before Java 5. The range of situations in which volatile is effective was expanded in Java 5; in particular, double checked locking now works correctly.