Что означает "атомарный" в программировании?

в эффективной книге Java говорится:

спецификация языка гарантирует, что чтение или запись переменная является атомной, если переменная не имеет типа long или double [JLS, 17.4.7].

что означает "атомарный" в контексте программирования Java или программирования в целом?

6 ответов


вот пример, потому что пример очень часто яснее, чем длинное объяснение. Предположим foo является переменной типа long. Следующая операция не атомарная операция:

foo = 65465498L;

действительно, переменная записывается с использованием двух отдельных операций: одна, которая записывает первые 32 бита, и вторая, которая записывает последние 32 бита. Это означает, что другой поток может прочитать значение foo, и увидеть промежуточное состояние.

сделать операция atomic состоит в использовании механизмов синхронизации, чтобы убедиться, что операция рассматривается из любого другого потока как единственная, атомарная (т. е. не расщепляемая по частям) операция. Это означает, что любой другой поток, как только операция будет выполнена атомарной, либо увидит значение foo до назначения или после назначения. Но не промежуточное значение.

простой способ сделать это-сделать переменной Летучий:

private volatile long foo;

или синхронизировать каждый доступ к переменной:

public synchronized void setFoo(long value) {
    this.foo = value;
}

public synchronized long getFoo() {
    return this.foo;
}
// no other use of foo outside of these two methods, unless also synchronized

или заменить его AtomicLong:

private AtomicLong foo;

"атомарная операция" означает операцию, которая кажется мгновенной с точки зрения всех других потоков. Вам не нужно потревожиться о частично полной деятельности когда гарантия применяется.


Это то, что" кажется остальной части системы, чтобы произойти мгновенно", и подпадает под категоризацию линеаризуемости в вычислительные процессы. Чтобы процитировать эту связанную статью дальше:

атомарность является гарантией изоляции от параллельных процессов. Кроме того, атомарные операции обычно имеют успех или неудачу определение-они либо успешно изменяют состояние системы, или не имеют явной эффект.

Так, например, в контексте базы данных системы, можно иметь атомные обязывает, т. е. вы можете нажать набора обновлений к реляционной базе данных, и эти изменения будут либо все, либо никто из них вообще в случае отказа, в этом случае данные не поврежден, а косвенные замков и/или очереди, следующей операцией будет другой писать или читать, но только после факт. В контексте переменные и потоки это почти то же самое, что и в памяти.

ваша цитата подчеркивает, что это нужно не ожидаемое поведение во всех случаях.


1) в языке структурированных запросов атомарная функция-это функция, которая завершит или вернется в исходное состояние, если прерывание питания или ненормальный конец происходит.

2) в некоторых операционных системах Unix атомарная операция-это операция, в которой не может произойти никаких изменений во времени между установкой маски и получением сигнала на изменение маски.

3) в некоторых языках программирования, включая Lisp , атом является базовой единицей исполняемого кода или данных.

операция, во время которой процессор может одновременно считывать местоположение и записывать его в той же операции шины. Это предотвращает любые другие процессор или устройство ввода-вывода от записи или чтения памяти до завершения операции.

Atomic подразумевает неделимость и неприводимость, поэтому атомная операция должна выполняться полностью или не выполняться вообще.


только что нашел сообщение атомарные и неатомные операции быть очень полезным для меня.

"операция, действующая на общую память, является атомной, если она завершается за один шаг относительно других потоков.

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

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


если у вас есть несколько потоков, выполняющих методы m1 и m2 в коде ниже:

class SomeClass {
    private int i = 0;

    public void m1() { i = 5; }
    public int m2() { return i; }
}

у вас есть гарантия, что какой-нить вызов m2 будет либо читать 0 или 5.

С другой стороны, с этим кодом (где i - это долго):

class SomeClass {
    private long i = 0;

    public void m1() { i = 1234567890L; }
    public long m2() { return i; }
}

какой-нить вызов m2 может читать 0, 1234567890L или какое-либо другое случайное значение, потому что оператор i = 1234567890L не гарантируется быть атомарным для long (JVM может написать первые 32 бита и последние 32 бита в двух операциях и потоке могут наблюдать i В между).