Oto przykład, ponieważ przykład jest często jaśniejszy niż długie wyjaśnienie. Załóżmy, że foo
jest zmienną typu long
. Następująca operacja nie jest operacją atomową:
foo = 65465498L;
Rzeczywiście, zmienna jest zapisywana za pomocą dwóch oddzielnych operacji: jednej, która zapisuje pierwsze 32 bity, i drugiej, która zapisuje ostatnie 32 bity. Oznacza to, że inny wątek może odczytać wartość foo
i zobaczyć stan pośredni.
Wykonanie operacji atomowej polega na użyciu mechanizmów synchronizacji, aby upewnić się, że operacja jest postrzegana, z dowolnego innego wątku, jako pojedyncza, atomowa (tj. Nierozdzielna na części) operacja. Oznacza to, że każdy inny wątek, po wykonaniu operacji atomowej, zobaczy albo wartośćfoo
przed przypisaniem, albo po przypisaniu. Ale nigdy wartość pośrednia.
Prostym sposobem na to jest uczynienie zmiennej zmienną :
private volatile long foo;
Lub zsynchronizuj każdy dostęp do zmiennej:
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
Lub zastąpić go AtomicLong
:
private AtomicLong foo;