В книге «Эффективная Java» говорится:
Спецификация языка гарантирует, что чтение или запись переменной является атомарным, если переменная не имеет тип
long
илиdouble
[JLS, 17.4.7].
Что означает «атомарный» в контексте программирования на Java или программирования в целом?
volatile long
илиvolatile double
делают чтение атомарным и запись атомарным.Ответы:
Вот пример, потому что пример часто яснее, чем длинное объяснение. Предположим
foo
, это переменная типаlong
. Следующая операция не является атомарной операцией:Действительно, переменная записывается с использованием двух отдельных операций: одна записывает первые 32 бита, а вторая - последние 32 бита. Это означает, что другой поток может прочитать значение
foo
и увидеть промежуточное состояние.Создание операции атомарной состоит в использовании механизмов синхронизации, чтобы убедиться, что операция рассматривается из любого другого потока как отдельная атомарная (т.е. не разделяемая на части) операция. Это означает, что любой другой поток после выполнения атомарной операции будет видеть значение
foo
до или после назначения. Но никогда не промежуточное значение.Простой способ сделать это - сделать переменную volatile :
Или синхронизировать каждый доступ к переменной:
Или заменить его на
AtomicLong
:источник
«Атомная операция» означает операцию, которая кажется мгновенной с точки зрения всех других потоков. Вам не нужно беспокоиться о частично завершенной операции, когда действует гарантия.
источник
Это то, что «кажется, что остальная часть системы происходит мгновенно», и подпадает под категоризацию линеаризуемости в вычислительных процессах. Чтобы процитировать эту связанную статью дальше:
Так, например, в контексте системы баз данных можно иметь «атомарные коммиты», что означает, что вы можете отправить набор изменений обновлений в реляционную базу данных, и эти изменения будут либо отправлены, либо ни одного из них вообще в В случае сбоя, таким образом, данные не становятся поврежденными и, как следствие, блокировок и / или очередей, следующей операцией будет другая запись или чтение, но только после факта. В контексте переменных и потоков это почти то же самое, применяется к памяти.
Ваша цитата подчеркивает, что такого поведения не следует ожидать во всех случаях.
источник
Только что обнаружил, что пост « Атомные и неатомные операции» мне очень помог.
источник
Если у вас есть несколько потоков, выполняющих методы m1 и m2 в коде ниже:
у вас есть гарантия, что любой вызывающий поток
m2
будет читать 0 или 5.С другой стороны, с этим кодом (где
i
длинный):вызывающий поток
m2
может прочитать 0, 1234567890L или другое случайное значение, потому что операторi = 1234567890L
не гарантированно является атомарным дляlong
(JVM может записать первые 32 бита и последние 32 бита в двух операциях, а поток может наблюдатьi
между ними) ,источник
В Java поля чтения и записи всех типов, кроме long и double, выполняются атомарно, и если поле объявляется с модификатором volatile, даже long и double атомарно считываются и записываются. То есть мы получаем 100% либо того, что там было, либо что там произошло, и не может быть никакого промежуточного результата в переменных.
источник