энергозависимое объявление типа int примитива - PullRequest
0 голосов
/ 16 мая 2018

Я цитирую из документации Oracle по Java Атомный доступ

  • Чтения и записи являются атомарными для ссылочных переменных и для большинства примитивных переменных (все типы, кроме long иdouble).
  • Чтение и запись являются атомарными для всех объявленных переменных volatile (включая длинные и двойные переменные).

Я понимаю, как работает volatile.Но упоминание о требовании явно объявить volatile для переменных long и double для получения атомарного доступа во втором выражении делает объявление volatile для ссылочных переменных и для большинства примитивных переменных (все типы, кроме long и double)в первом утверждении необязательно.

Но я вижу коды, которые используют явное объявление volatile в int примитивном типе для достижения атомарного доступа;и не делает этого, не гарантируя атомарный доступ.

int variable1;          // no atomic access
volatile int variable2; // atomic access

Я что-то упустил?

Ответы [ 2 ]

0 голосов
/ 16 мая 2018

Ключевое слово volatile обеспечивает не только атомарный доступ, но и гарантии видимости .

Поскольку примитивы double и long занимают вдвое больше места, чем int (64 бита), обновление их значений может происходить в двух 32-битных блоках. Таким образом, без изменчивости вы могли видеть значение long или double между этими двумя шагами. Это не относится к другим примитивным переменным.

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

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

Java-параллелизм на практике: 3.1.4. Изменчивые переменные

0 голосов
/ 16 мая 2018

Первый оператор не относится к созданию ссылочных переменных и примитивных переменных (за исключением long и double) volatile.

Он говорит читает и записывает всех ссылочных переменных и всех примитивов, кроме long и double, равных atomic (по умолчанию).Чтобы читает и пишет из long и double атомный они должны быть volatile.

Атомность не имеетчто-либо связанное с visibility .

Следующий абзац того же документа

Атомарные действия не могут быть чередованы, поэтому они могут использоваться без боязни вмешательства потока,Однако это не устраняет всей необходимости синхронизировать атомарные действия, поскольку ошибки согласованности памяти все еще возможны.Использование энергозависимых переменных снижает риск ошибок согласованности памяти, потому что любая запись в энергозависимую переменную устанавливает отношение «происходит до» с последующим чтением этой же переменной.

Итак, операторы типа a = 1, где a - это int (например) atomic , но вам все еще нужно иметь volatile , если вы хотите, чтобы назначение было видимым для любого последующего чтенияпотоки.

Чтение / запись в переменную long / double является сложным действием, и volatile гарантирует, что оно атомарно.

...