Пометка переменной как volatile
в Java гарантирует, что каждый поток увидит последнее записанное в него значение вместо некоторого устаревшего значения. Мне было интересно, как это на самом деле достигается. Выдает ли JVM специальные инструкции, которые очищают кэш-память ЦП или что-то в этом роде?
Как на самом деле работает volatile?
Ответы (2)
Насколько я понимаю, это всегда выглядит так, как будто кеш был очищен после записи, и всегда выглядит так, как будто чтение выполняется прямо из памяти при чтении. Эффект состоит в том, что поток всегда будет видеть результаты записи из другого потока и (согласно модели памяти Java) никогда не будет кэшированного значения. Однако фактическая реализация и инструкции ЦП будут отличаться от одной архитектуры к другой.
Это не гарантирует правильности, если вы увеличиваете переменную более чем в одном потоке или проверяете ее значение и предпринимаете какие-либо действия, поскольку, очевидно, нет фактической синхронизации. Как правило, вы можете гарантировать правильное выполнение только в том случае, если в переменную записывается только поток, а все остальные читают.
Также обратите внимание, что 64-битная НЕЛЕТУЧАЯ переменная может быть прочитана / записана как две 32-битные переменные, поэтому 32-битные переменные являются атомарными при записи, а 64-битные - нет. Одна половина может быть записана перед другой, так что прочитанное значение может быть не старым или новым.
Это довольно полезная страница из моих закладок:
http://www.cs.umd.edu/~pugh/java/memoryModel/
volatile
s не обязательно должны быть немедленными, если это не нарушает правила происходит до. Например, компилятор может объединить две записи в изменчивую переменную, если между ними не произойдет другого поведения "произошло раньше".
- person Tom Hawtin - tackline; 02.11.2011
То, что происходит, зависит от процессора. Как правило, существуют инструкции по ограничению памяти. Очистка всей кеш-памяти, очевидно, будет очень дорогой - в аппаратном обеспечении есть протоколы согласованности кеш-памяти.
Также важно, чтобы не производилась определенная оптимизация доступа к полям. Компилятор важен при рассмотрении многопоточности, не думайте только об оборудовании.