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