Являются атомарными присвоения на 64 бита в Java на машине на 32 бита?

Если у меня есть код как это -

long x;
x  = 0xFFFFFFFFL;


Если я работаю, этот код машины на 32 бита - это, гарантировал, что был атомарным, или действительно ли возможно, что другой поток, читая x, мог бы получить неполное значение / значение мусора?

27
задан pdeva 11 August 2010 в 23:33
поделиться

4 ответа

Вот краткое изложение:

  • Для ссылок чтение / запись ВСЕГДА атомарны (даже в 64-битных реализациях!)
  • Для int , char , байт , короткое , логическое , с плавающей точкой , чтение / запись ] ВСЕГДА атомарный
  • Для double и long , если они изменчивые , чтение / запись ВСЕГДА атомарное

Поэтому существует единственное исключение, когда операции чтения / записи не могут быть атомарными:

  • Для double и long , если они НЕ объявлены volatile , они НЕ ГАРАНТИРУЮТСЯ , чтобы быть атомарными

Что касается атомарности чтения / записи общих данных, вам нужно только сделать volatile любой двойной или длинный .Все остальное уже гарантированно атомарно, независимо от того, сколько битов используется в реальной реализации.


О спецификации

Вот соответствующий раздел, воспроизведенный здесь для быстрого ознакомления:

JLS 17.7 Неатомарная обработка double и long

Некоторые реализации могут счесть это удобным для разделения одного действия записи на 64-битное длинное или двойное значение на два действия записи на смежных 32-битных значениях. Ради эффективности это поведение зависит от реализации; Виртуальные машины Java могут выполнять запись в значения long и double атомарно или двумя частями.

В рамках модели памяти языка программирования Java однократная запись в не- volatile long или двойное значение обрабатывается как две отдельные записи: по одной в каждое 32- немного наполовину. Это может привести к ситуации, когда поток видит первые 32 бита 64-битного значения при одной записи, а вторые 32 бита - при другой записи. Запись и чтение значений volatile long и double всегда атомарны. Запись и чтение ссылок всегда атомарны, независимо от того, реализованы ли они как 32- или 64-битные значения.

Разработчикам VM рекомендуется по возможности избегать разделения своих 64-битных значений. Программистам рекомендуется объявлять общие 64-битные значения как volatile или правильно синхронизировать свои программы, чтобы избежать возможных осложнений.

См. Также

Связанные вопросы

48
ответ дан 28 November 2019 в 04:24
поделиться

В разделе 8.4 спецификации виртуальной машины Java говорится, что double или long, которые не объявлены volatile, обрабатываются как две 32-битные переменные для операций загрузки, сохранения, чтения и записи.

Кроме того, не определены способ кодирования и порядок двух 32-битных операций.

Спецификация поощряет реализации делать операцию атомарной, но они этого не требуют.

9
ответ дан 28 November 2019 в 04:24
поделиться

Если переменная энергозависимая , то чтение / запись гарантируется атомарно, но не в том случае, если переменная энергонезависима.

В некоторых реализациях может оказаться удобным разделить одну запись действие на 64-битной длинной или двойной значение на два действия записи на смежные 32-битные значения. За ради эффективности, такое поведение конкретная реализация; Виртуальная Java машины могут выполнять запись в длинные и двойные значения атомарно или в двух частях.

Для модели памяти языка программирования Java однократная запись в энергонезависимую длинную или двойное значение рассматривается как два отдельные записи: по одной на каждую 32-битную половина. Это может привести к ситуации где поток видит первые 32 бита 64-битного значения от одной записи, и вторые 32 бита из другой записи. Записывает и читает летучие длинные и двойные значения всегда атомарны.

JLS 17.7 - Неатомарная обработка двойных и длинных

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

8
ответ дан 28 November 2019 в 04:24
поделиться

Нет, это не так. 64-битное хранилище рассматривается как два отдельных 32-битных хранилища. Поэтому в параллельной среде эта переменная может иметь старшие 32 бита одной записи и младшие 32 бита другой записи, что явно не безопасно для потоков.

11
ответ дан 28 November 2019 в 04:24
поделиться