Cosa significa "atomico" nella programmazione?


276

Nel libro Effective Java, afferma:

La specifica del linguaggio garantisce che la lettura o la scrittura di una variabile è atomica a meno che la variabile non sia di tipo longo double[JLS, 17.4.7].

Che cosa significa "atomico" nel contesto della programmazione Java o della programmazione in generale?


24
Un'operazione alla volta.
Subhrajyoti Majumder,

1
è possibile eseguire una sola operazione alla volta.
Kaysush,


1
sospetto che le domande di filosofia appartengano a codereview.stackexchange.com
Phlip

Notando che alcune variabili per impostazione predefinita non hanno lettura e scrittura atomiche, dichiarandole come volatile longo volatile doublerendono la lettura atomica e la scrittura atomica.
H2ONaCl

Risposte:


372

Ecco un esempio, perché un esempio è spesso più chiaro di una lunga spiegazione. Supponiamo che foosia una variabile di tipo long. La seguente operazione non è un'operazione atomica:

foo = 65465498L;

In effetti, la variabile viene scritta usando due operazioni separate: una che scrive i primi 32 bit e una seconda che scrive gli ultimi 32 bit. Ciò significa che un altro thread potrebbe leggere il valore di fooe vedere lo stato intermedio.

Rendere l'operazione atomica consiste nell'utilizzare meccanismi di sincronizzazione per assicurarsi che l'operazione venga vista, da qualsiasi altro thread, come un'operazione singola, atomica (cioè non suddivisibile in parti). Ciò significa che qualsiasi altro thread, una volta che l'operazione è stata resa atomica, vedrà il valore fooprima dell'assegnazione o dopo l'assegnazione. Ma mai il valore intermedio.

Un modo semplice per farlo è rendere volatile la variabile :

private volatile long foo;

O per sincronizzare ogni accesso alla variabile:

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

O per sostituirlo con un AtomicLong:

private AtomicLong foo;

75
Quindi questo presuppone che sia in esecuzione in un sistema a 32 bit. E se fosse un sistema a 64 bit? Will foo = 65465498L; essere atomico allora?
Harke,

46
@Harke Se si esegue Java a 64 bit, sì.
Jeroen,

4
Questo vale anche per C # e .NET? Se sì, per ottenere un comportamento atomico, il CLR deve essere a 64 bit?
Fabiano,

5
@Fabiano Si applica ed ecco come raggiungerlo in .NET poiché non abbiamo la parola chiave sincronizzata come Java. stackoverflow.com/questions/541194/…
The Muffin Man,

2
Quindi supponiamo che il thread A assegni un valore lungo, quindi a metà strada il thread B prova a leggerlo. Se l'operazione A è atomica, il thread B attenderà fino al termine? Ciò significa che le operazioni atomiche forniranno la sicurezza implicita del thread?
Teoman Shipahi,

60

"Operazione atomica" indica un'operazione che sembra essere istantanea dal punto di vista di tutti gli altri thread. Non è necessario preoccuparsi di un'operazione parzialmente completa quando si applica la garanzia.


25

È qualcosa che "sembra accadere istantaneamente al resto del sistema" e rientra nella categorizzazione della linearità nei processi di elaborazione. Per citare ulteriormente l'articolo collegato:

L'atomicità è una garanzia di isolamento dai processi concorrenti. Inoltre, le operazioni atomiche hanno comunemente una definizione di esito positivo o negativo: cambiano correttamente lo stato del sistema o non hanno alcun effetto apparente.

Quindi, ad esempio, nel contesto di un sistema di database, si possono avere "commit atomici", il che significa che è possibile inviare una serie di aggiornamenti a un database relazionale e tali modifiche verranno tutte inviate o nessuna di esse in in caso di errore, in questo modo i dati non vengono danneggiati e conseguenti a blocchi e / o code, l'operazione successiva sarà una scrittura o una lettura diversa, ma solo dopo il fatto. Nel contesto delle variabili e del threading questo è più o meno lo stesso, applicato alla memoria.

Il tuo preventivo evidenzia che non è necessario prevedere un comportamento in tutti i casi.


15

Ho appena trovato un post Atomic vs. Non-Atomic Operations molto utile per me.

"Un'operazione che agisce sulla memoria condivisa è atomica se si completa in un singolo passaggio rispetto ad altri thread.

Quando un archivio atomico viene eseguito su una memoria condivisa, nessun altro thread può osservare la modifica completata a metà.

Quando un carico atomico viene eseguito su una variabile condivisa, legge l'intero valore come appariva in un singolo momento. "


14

Se hai diversi thread che eseguono i metodi m1 e m2 nel codice seguente:

class SomeClass {
    private int i = 0;

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

hai la garanzia che qualsiasi chiamata di thread m2leggerà 0 o 5.

D'altra parte, con questo codice (dove iè un lungo):

class SomeClass {
    private long i = 0;

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

una chiamata a thread m2potrebbe leggere 0, 1234567890L o qualche altro valore casuale perché i = 1234567890Lnon è garantito che l'istruzione sia atomica per a long(una JVM potrebbe scrivere i primi 32 bit e gli ultimi 32 bit in due operazioni e un thread potrebbe osservare iin mezzo) .


perché pensi che "long" causi problemi mentre "int" no? Si prega di consultare qui geekswithblogs.net/BlackRabbitCoder/archive/2012/08/09/…
onmyway133

1
Le assegnazioni lunghe e doppie di @entropy non sono garantite come atomiche in Java. Quindi potresti leggere a lungo dove solo metà dei bit sono stati aggiornati a seguito di un'assegnazione.
Assylias,

0

In Java la lettura e la scrittura di campi di tutti i tipi, tranne long e double, si verificano atomicamente e se il campo viene dichiarato con il modificatore volatile, anche long e double vengono letti e scritti atomicamente. Cioè, otteniamo il 100% di ciò che era lì o di ciò che è accaduto lì, né può esserci alcun risultato intermedio nelle variabili.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.