Мы знаем, что операции установки значений переменных в Java являются атомарными операциями, за исключением переменных типа long и double. Другими словами, нет необходимости синхронизировать простые операции чтения и записи значений переменных.
До JVM 1.2 реализация модели памяти Java всегда считывала переменные из основной памяти, что не требовало особого внимания. С развитием и оптимизацией JVM использование изменчивых ключевых слов стало очень важным в многопоточных средах. В соответствии с текущей моделью памяти Java потоки могут хранить переменные в локальной памяти (например, в машинных регистрах) вместо прямого чтения и записи в основную память. Это может привести к тому, что один поток изменит значение переменной в основной памяти, в то время как другой поток продолжит использовать свою копию значения переменной в регистре, что приведет к несогласованности данных. Чтобы решить эту проблему, вам нужно всего лишь объявить переменную как изменчивую (нестабильную), как в этой программе. Это указывает JVM, что эта переменная нестабильна и будет сохраняться в основной памяти каждый раз, когда она используется для чтения. Вообще говоря
Поэтому в многозадачной среде флаги, разделяемые задачами, должны быть изменены с помощью Volatible.
Каждый раз, когда поток обращается к переменной-члену, измененной с помощью Volatile, значение переменной-члена принудительно пересчитывается из общей памяти. Более того, когда изменяется переменная-член, поток вынужден записать измененное значение обратно в общую память. Таким образом, в любой момент два разных потока всегда видят одно и то же значение переменной-члена.
В спецификации языка Java говорится: Для оптимальной скорости потокам разрешено сохранять частные копии общих переменных-членов и сравнивать их с исходными значениями общих переменных-членов только тогда, когда поток входит или покидает синхронизированный блок кода.
Таким образом, когда несколько потоков одновременно взаимодействуют с объектом, необходимо уделять внимание тому, чтобы потоки могли своевременно получать изменения в общих переменных-членах.
Ключевое слово volutity подсказывает виртуальной машине: она не может сохранить частную копию этой переменной-члена, но должна напрямую взаимодействовать с общей переменной-членом.
Предложение по использованию: используйте переменные для переменных-членов, к которым имеют доступ два или более потоков. Нет необходимости использовать его, если переменная, к которой осуществляется доступ, уже находится в синхронизированном блоке кода или является константой.
Поскольку использование Летучих блокирует необходимую оптимизацию кода в ВМ, оно менее эффективно, поэтому это ключевое слово следует использовать только при необходимости.
В реализации виртуальной машины базовые типы, такие как int и char, имеют длину в одно слово. А long и double занимают по длине два слова. В некоторых реализациях виртуальных машин две длины слова могут рассматриваться как две атомарные длины одного слова.
Если long и double не модифицируются с помощью flaming, если к переменной обращаются несколько потоков, результат будет запутанным из-за общей неатомарности длинной операции.
Например: int, один поток записывает 4, а другой — 5. Конечное значение должно быть 4 или 5. А длинный тип может быть беспорядочным значением.