Что означает «изменчивый» в Java? - PullRequest
24 голосов
/ 03 февраля 2011

Мы используем volatile в одном из наших проектов для поддержки одной и той же копии переменной, к которой обращаются разные потоки. У меня вопрос, можно ли использовать volatile с static. Компилятор не выдает никаких ошибок, но я не понимаю причину использования обоих.

Ответы [ 5 ]

18 голосов
/ 05 февраля 2011

Если не считать спецификации модели памяти, я рекомендую вам прочитать http://jeremymanson.blogspot.com/2008/11/what-volatile-means-in-java.html. Она написана одним из авторов JMM и должна ответить на ваш вопрос. Также полезно думать о чтении и записи памяти в терминах предложения произойдет до ; JMM для Java 5 и выше добавляет семантику «до и после» к volatile.

В частности, когда вы читаете энергозависимую переменную из одного потока, все записи, включая запись в эту энергозависимую переменную из других потоков, теперь видны этому потоку. Если у вас есть какое-то время, есть технический доклад Google, в котором дополнительно обсуждается тема: https://code.google.com/edu/languages/#_java_memmodel.

И, да, вы можете использовать static с volatile. Они делают разные вещи.

11 голосов
/ 05 февраля 2011

В Java volatile имеет такое же общее значение, как и в C. Модель памяти Java (см. Превосходную ссылку в ответе ide) позволяет потокам одновременно «видеть» другое значение для переменных, помеченных как не имеющие значения. неустойчивый. Например:

Тема:

n = 1;
// wait...
n = 2;

Резьбы B и C:

while (true) {
    System.out.println(name + ": " + n);
}

Этот вывод разрешен (обратите внимание, что вы не гарантированно строго чередуетесь между B и C, я просто пытаюсь показать здесь «замену» B и C):

C: 1
B: 1
C: 2
B: 1
C: 2
B: 2

Это совершенно отдельно от замка, взятого println; поток B позволяет видеть n как 1 даже после того, как C узнает, что это 2. Есть множество очень веских причин для этого, что я не могу притворяться, что полностью понимаю, многие из которых касаются скорости и некоторые, относящиеся к безопасности.

Если он изменчив, вы гарантированно (кроме блокировки println, которую я пока проигнорирую), что B и C оба "одновременно" увидят новое значение B, как только оно отправлено.

Вы можете использовать volatile с static, потому что они влияют на разные вещи. volatile приводит к тому, что изменения "реплицируются" во все потоки , которые используют эту переменную, прежде чем они ее используют, в то время как static совместно использует одну переменную для всех классов , которые используют эту переменную. переменная. (Это может немного сбить с толку тех, кто плохо знаком с потоками в Java, потому что каждый Thread реализован как class.)

8 голосов
/ 05 февраля 2011

volatile означает, что переменная изменяется во время выполнения и что компилятор не должен кэшировать свое значение по любой причине.

Это на самом деле проблема только при совместном использовании переменной между потоками, вы не хотите, чтобы поток работал с устаревшими данными, поэтому компилятор никогда не должен кэшировать значение volatile ссылки на переменную.

2 голосов
/ 09 августа 2017

Рассмотрим сценарий, когда два потока (Thread1 и Thread2) обращаются к одной и той же переменной 'mObject' со значением 1.

, когда выполняется Thread1, он не ожидает, что другие потоки изменят переменную 'mObject',В этом сценарии Thread1 кэширует переменную 'mObject' со значением 1.

И если Thread2 изменяет значение 'mObject' на 2, все равно Thread1 будет ссылаться на значение mObject как 1, так как он кэшировал,Чтобы избежать этого кэширования, мы должны объявить переменную как

private volatile int mObject;

, в этом случае Thread1 будет получать обновленное значение mObject

2 голосов
/ 23 июля 2015

Volatile используется во многих различных ситуациях, когда нескольким потокам необходим доступ к одной и той же переменной.Многие люди, не занимающиеся многопоточным / параллельным программированием, не будут подвержены этому.Volatile гарантирует, что переменная всегда читается из основной памяти, а не из версии кэша / регистра.Волатильность сама по себе не является блокировкой, просто потому, что изменения видны всеми потоками, как только они записаны, не означает, что вы можете сравнивать и заменять их атомарным способом.Однако эту функцию можно использовать с другими функциями, такими как сравнение и замена, для создания структур данных, которые являются потокобезопасными, не требуя от пользователя более тяжелой семантики ожидания-уведомления java.

вы можете получить большеинформация по этой ссылке http://www.quora.com/Threading-in-Java/What-is-the-purpose-of-the-volatile-keyword-in-java

...