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

64-разрядные назначения в Java-атоме на 32-битной машине?

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

long x;
x  = 0xFFFFFFFFL;


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

4b9b3361

Ответ 1

Вот краткое резюме:

  • Для ссылок, чтения/записи ВСЕГДА атомные (даже в 64-битных реализациях!)
  • Для int, char, byte, short, boolean, float, чтение/запись ВСЕГДА атомный
  • Для double и long, если они volatile, чтение/запись ALWAYS atomic

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

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

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


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

Здесь соответствующий раздел воспроизводится здесь для быстрой справки:

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

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

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

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

См. также

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

Ответ 2

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

Ответ 3

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

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

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

Ответ 4

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

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

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

JLS 17.7 - Неатомное обращение с двойным и длинным

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