Подтвердить что ты не робот

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

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

4b9b3361

Ответ 1

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

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

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

Ответ 2

В 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.)

Ответ 3

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

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

Ответ 4

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

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

Ответ 5

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

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

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

закрытый volatile int mObject;

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

Ответ 6

Небольшая разработка, но ключевое слово volatile не только для видимости памяти. Перед выпуском Java ver 1.5 ключевое слово volatile объявило, что поле получит самое последнее значение объекта, каждый раз обращаясь к основной памяти для чтения и сбрасывая для записи.

В последних версиях Java ключевое слово volatile говорит о двух очень важных вещах:

  1. Не волнуйтесь о том, как, но знайте, что, читая изменчивое поле у вас всегда будет самая актуальная стоимость.
  2. Компилятор не может переупорядочить изменчивое чтение/запись для поддержания порядка программы.

Ознакомьтесь с другими волатильными примерами на Java.