Что означает «изменчивость» в Java?

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

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

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

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

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

Тема:

 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 вызывает изменение переменной, которая должна быть «реплицирована» во все streamи, которые используют эту переменную, прежде чем они ее используют, а static – одну переменную для всех classов , использующих эту переменную. (Это может быть довольно запутанным для людей, новых для streamовой передачи на Java, потому что каждый Thread реализуется как class .)

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

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

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

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

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

когда Thread1 работает, он не ожидает, что другие streamи изменят переменную «mObject». В этом случае Thread1 кэширует переменную ‘mObject’ со значением 1.

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

private volatile int mObject;

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

  • Volatile boolean vs AtomicBoolean
  • Неправильное ключевое слово C ++ вовлекает забор памяти?
  • Давайте будем гением компьютера.