Сегодня встретил такой код
class someClass {
// ...
private volatile int a;
// ...
}
Вопрос в том, что такое volatile в данном контексте?
Сегодня встретил такой код
class someClass {
// ...
private volatile int a;
// ...
}
Вопрос в том, что такое volatile в данном контексте?
Модификатор volatile накладывает некоторые дополнительные условия на чтение/запись переменной. Важно понять две вещи о volatile переменных:
Кажется, что для человека, задающего вопрос вроде вашего, достаточно знать эти два момента.
Some implementations may find it convenient to divide a single write action on a 64-bit long or double value into two write actions on adjacent 32-bit values. For efficiency's sake, this behavior is implementation-specific; an implementation of the Java Virtual Machine is free to perform writes to long and double values atomically or in two parts.
– a_gura Mar 03 '20 at 17:29Результат операции записи значения в volatile переменную одним потоком, становится виден ... - верно, но нужно дополнить Результат операции записи значения в volatile переменную одним потоком, а так же все результаты записи в другие переменные сделанные до записи в volatile переменную этим же потоком, становятся видны ...
– Roman-Stop RU aggression in UA
Nov 26 '20 at 14:10
Операции чтения/записи volatile переменной являются атомарными. - безопасными атомарными операциями являются чтение и присвоение примитивов, кроме long и double. Атомарность можно обеспечить, определяя переменные long и double с ключевым словом volatile.
– West Side
May 31 '21 at 15:45
Это означает, что значение переменной будет "всегда читаться". Например, в многопоточных приложениях один поток прочёл значение a=1, передал управление другому потоку, который изменил значение на a=2, потом управление вернулось. Так вот, без volatile значение a у первого потока будет 1, т.к. первый поток "помнит", что a=1, с volatile - 2, т.к. первый поток снова прочтет значение и получит уже измененное.
у переменной есть мастер копия плюс по копии на каждую нить, что её используют. Мастер копия синхронизируется с локальной копией нити при входе/выходе в/из блока synchronized. Иногда, например, пустой блок synchronized(lock){} имеет смысл.
у переменных с модификатором volatile локальных копий нет. Все нити работают с мастер копией.
Ещё надо отметить, что volatile не панацея при кодировании нескольких нитей: если используются неатомарные операции, например += или ++
– bbk75 Jan 20 '11 at 22:06Вот какое определение дается в статье «Многопоточность Java» на сайте http://alfalavista.ru.
Определение переменной с ключевым словом
volatileозначает, что значение этой переменной может изменяться другими потоками. Чтобы понять, что делаетvolatile, полезно разобраться, как потоки обрабатывают обычные переменные.В целях повышения производительности спецификация языка Java допускает сохранение в JRE локальной копии переменной для каждого потока, который на нее ссылается. Такие "локальные" копии переменных напоминают кэш и помогают потоку избежать обращения к главной памяти каждый раз, когда требуется получить значение переменной. При запуске двух потоков один из них считывает переменную A как 5, а второй ― как 10. Если значение переменной А изменилось с 5 на 10, то первый поток не узнает об изменении и будет хранить неправильное значение A. Но если переменная А помечена как
volatile, то когда бы поток не считывал значение A, он будет обращаться к главной копии A и считывать ее текущее значение. Локальный кэш потока имеет смысл в том случае, если переменные в ваших приложениях не будут изменяться извне.Если переменная объявлена как
volatile, это означает, что она может изменяться разными потоками. Естественно ожидать, что JRE обеспечит ту или иную форму синхронизации таких volatile-переменных. JRE действительно неявно обеспечивает синхронизацию при доступе к volatile-переменным, но с одной очень большой оговоркой: чтение volatile-переменной и запись в volatile-переменную синхронизированы, а неатомарные операции ― нет.
для объектным ссылок volatile можно не писать. я прав?
Например, когда мы в многопоточном приложении используем паттерн Синглтон в котором применяем синхронизацию и хотим чтобы синхронизация осуществлялась только один раз при инициализации объекта, а не каждый раз, когда мы вызываем getInstance(), тогда модификатора volatile используем для объектной ссылки:
public class Singleton {
private static volatile Singleton instance;
private Singleton(){
}
public static Singleton getInstance() {
if (instance == null) {
synchronized(Singleton.class) {
if (instance == null)
instance = new Singleton();
}
}
return instance;
}
}
volatile - буквально означает летучий, непостоянный, изменчивый
в контексте программирования это означает, что значение переменной может неожиданно изменяться, поэтому не стоит полагаться на значения этой переменной, например, если в коде написано:
private volatile int i;
// через некоторое время
i=0;
while(i < 10) {
//blah-blah
i++;
}
это не означает, что цикл точно завершится через 10 шагов...
вполне может случиться, что в ходе выполнения цикла значение volatile переменной будет неожиданным образом меняться (а может и не будет меняться)...
volatile определяется например каким-нибудь драйвером/датчиком чего-нибудь, который не поддается синхронизации средствами Java
– Barmaley
Feb 12 '19 at 06:16
volatile - говорит потоку что переменная может меняться, и информирует поток о необходимости обращаться к последней версии, а не к хешированной копии и своевременно распространять изменения.
A "volatile" data member informs a thread, both to get the latest value for the variable (instead of using a cached copy) and to write all updates to the variable as they occur.