Являются ли 64-битные назначения в Java атомарными на 32-битной машине? - PullRequest
26 голосов
/ 12 августа 2010

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

long x;
x  = 0xFFFFFFFFL;

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

Ответы [ 4 ]

47 голосов
/ 12 августа 2010

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

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

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

  • Для 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-битные значения.

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

Смотри также

Похожие вопросы

11 голосов
/ 12 августа 2010

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

9 голосов
/ 12 августа 2010

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

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

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

8 голосов
/ 12 августа 2010

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

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

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

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...