Если у меня есть такой код -
long x;
x = 0xFFFFFFFFL;
Если я запустил этот код на 32-битной машине, он гарантированно будет атомарным или, возможно, что другой поток, читающий x, может получить неполное/мусорное значение?
Если у меня есть такой код -
long x;
x = 0xFFFFFFFFL;
Если я запустил этот код на 32-битной машине, он гарантированно будет атомарным или, возможно, что другой поток, читающий x, может получить неполное/мусорное значение?
Вот краткое резюме:
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
или правильно синхронизировать их программы, чтобы избежать возможных осложнений.
byte
может быть обновлен без соседних помех.volatile
Поляint i;
, i++
НЕ атомный!volatile long[]
- это volatile
ссылка на массив long
long
не являются volatile
Нет, это не так. 64-битное хранилище рассматривается как два отдельных 32-разрядных хранилища. Таким образом, в параллельной среде эта переменная может иметь максимум 32 одной записи, а нижняя 32 другой записи, очевидно, не является безопасной по потоку.
В разделе 8.4 спецификации виртуальной машины Java указано, что двойной или длинный, который не объявлен volatile, рассматривается как две 32-разрядные переменные для операций загрузки, хранения, чтения и записи.
Кроме того, способ кодирования и порядок двух 32-разрядных операций не определены.
Спецификация поощряет реализации, чтобы сделать операцию атомой, но она не требует ее.
Если переменная volatile
, то чтение/запись гарантируется атомом, но не если переменная нестабильна.
В некоторых реализациях может оказаться удобным разделить одну запись действие на 64-битный или двойной значение в два действия записи на смежные 32-битные значения. Для эффективность, это поведение конкретная реализация; Виртуальный виртуальный машины могут выполнять записи в длинные и двойные значения атомарно или в двух частях.
В целях модели памяти языка программирования Java однократная запись в энергонезависимую длинную или двойное значение рассматривается как два отдельные записи: по одному на каждый 32-разрядный половина. Это может привести к ситуации где поток видит первые 32 бита из 64-битного значения из одной записи и второй 32 бита из другой записи. Пишет и читает летучие длинные и двойные значения всегда являются атомарными.
JLS 17.7 - Неатомное обращение с двойным и длинным
Когда несколько потоков обращаются к длинному значению без синхронизации, необходимо использовать volatile
, чтобы гарантировать, что изменения, сделанные одним потоком, видны другим потокам и обеспечить, чтобы чтение/запись было атомарным.