Jakie operacje w Javie są uważane za atomowe?

Odpowiedzi:

100
  • wszystkie przypisania typów pierwotnych z wyjątkiem long i double
  • wszystkie przypisania referencji
  • wszystkie przypisania zmiennych lotnych
  • wszystkie operacje klas java.concurrent.Atomic *

a może coś więcej. Spójrz na jls .

Jak zauważono w komentarzach, atomowość nie oznacza widoczności. Więc chociaż gwarantuje się int, że inny wątek nie zobaczy części zapisanej , może nigdy nie zobaczyć nowej wartości.

Operacje na long i double są również wykonywane na zwykłych atomowych procesorach 64-bitowych , chociaż nie ma gwarancji. Zobacz także tę prośbę o funkcję .

maaartinus
źródło
21
Przypisania do giervolatile długich i podwójnych z pewnością będą atomowe: java.sun.com/docs/books/jls/third_edition/html/memory.html#17.7
Joonas Pulakka
12
Ponadto, należy pamiętać, że podczas gdy operacje są niepodzielne, widoczność z tych operacji nie może być zagwarantowane w wielowątkowych aplikacji, chyba że jest zachować szczególną ostrożność (tutaj szczegóły są sposobem na zawiły opisać w komentarzu ..)
nr
5
64 bit jvm, long and double assignments are also atomic.Jesteś pewny? Powiedziałbym, że są przeznaczone do skompilowanego kodu, ale co z kodem interpretowanym? Prawdopodobnie masz rację, ale czy jest jakaś gwarancja?
maaartinus
4
Specyfikacja nadal nie wymaga, aby 64-bitowe maszyny JVM zapewniały atomowość w przypadku długich i podwójnych przypisań. java.sun.com/docs/books/jls/third_edition/html/memory.html#17.7 W słynnych słowach „to zachowanie jest specyficzne dla implementacji”. Jednak najprawdopodobniej 64-bitowe maszyny wirtualne wdrożyłyby to jako operację atomową.
sjlee
1
IMHO, normalne przypisania referencyjne są atomowe, ale AtomicReference oferuje więcej: compareAndSet i getAndSet, czego nie można by osiągnąć bez synchronizacji.
maaartinus
5

W Javie gwarantuje się atomowe odczytywanie i zapisywanie ilości 32-bitowych lub mniejszych.
Przez atomową rozumiemy, że każda akcja odbywa się w jednym kroku i nie można jej przerwać. Tak więc, gdy mamy aplikacje wielowątkowe, operacje odczytu i zapisu są bezpieczne dla wątków i nie muszą być synchronizowane.

Na przykład poniższy kod jest bezpieczny dla wątków:

public class ThreadSafe   
  {  
    private int x;  
    public void setX(int x)  
          {
           this.x = x;
           } 
  }
sgokhales
źródło
5
..threads safe w tym sensie, że wartość zawsze będzie dokładnie albo wartością oryginalną, albo wartością ustawioną. Większość aktualnych wartości nadal nie jest widoczna dla innych wątków ze względu na brak wartości „nietrwałych” lub „zsynchronizowanych”.
Mikko Wilkman
1
+1 do tego, co mówi @MikkoWilkman. Tego fragmentu kodu nie należy używać, ponieważ z punktu widzenia widoczności pamięci zdecydowanie nie jest bezpieczny wątkowo.
Knuckles the Echidna
0

Wydawałoby się, że przypisania longs są atomowe, oparte na tej metodzie w AtomicLong.java:

public final void set(long newValue) {
    value = newValue;
}

Zwróć uwagę na brak jakiejkolwiek synchronizacji.

Lyle Z
źródło
3
Spójrz na deklarację value. To jest volatile.
maaartinus
2
Że valueto volatilenie czyni przypisanie valueatomowych, to po prostu unika „Publikowanie” kwestii.
Lyle Z
7
Robi jedno i drugie, zobacz JLS, sekcja 17.7 : Zapisy i odczyty zmiennych wartości long i double są zawsze atomowe.
maaartinus
@LyleZ moim zdaniem najcenniejszy komentarz w tym wątku.
stdout