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