2008-11-11 28 views

Odpowiedz

89

Krótka odpowiedź brzmi: Nie

Z java.util.concurrent.atomic package doc:

Efekty pamięci dla dostępów i aktualizacji atomistyki ogólnie przestrzegać zasady lotne:

  • get ma pamięć efekty odczytu zmiennej volatile.
  • set ma pamięć efektów pisania (przypisywania) zmiennej volatile.

Nawiasem mówiąc, doc dla pakietu jest bardzo dobra i wszystko jest wyjaśnione ...


lazySet (wprowadzony w Javie 6) jest nowsza operacja wprowadzona że ma semantykę nieosiągalne poprzez zmienne volatile; Aby uzyskać więcej informacji, patrz this post.

+2

A dłuższa odpowiedź byłaby? –

+0

Uzgodnione. Potrzebujemy przynajmniej łącza. –

+2

Link do dłuższej odpowiedzi: http://java.sun.com/j2se/1.5.0/docs/api/java/util/concurrent/atomic/package-summary.html –

37

Nie, nie ma.

Dodatkowa moc dostarczana przez AtomicReference to metoda compareAndSet() i przyjaciele. Jeśli nie potrzebujesz tych metod, zmienne odniesienie zapewnia tę samą semantykę, co AtomicReference.set() i .get().

3

AtomicReference zapewnia dodatkową funkcjonalność, której nie zapewnia zwykła zmienna lotna. Jak już czytałeś API, wiesz o tym, ale zapewnia również blokadę, która może być przydatna w niektórych operacjach.

Jednakże, jeśli nie potrzebujesz tej dodatkowej funkcjonalności, sugeruję użycie zwykłego pola zmiennego.

+0

Różnica polega na tym, że ich występ. Gdyby nie było różnicy, nigdy byś nie sugerował używania jednej z drugiej. –

+0

Wydajność jest bardzo podobna. AtomicRefrence zwiększa złożoność i zużycie pamięci. –

+0

@BT Pole 'volatile' może być używane jak zwykłe pole, podczas gdy dostęp do wartości w' AtomicReference' wymaga przechodzenia przez metody 'get' i' set'. –

6

JDK source code jest jednym z najlepszych sposobów na odpowiedź na konfuzje takie jak ta. Jeśli spojrzysz na kod w AtomicReference, używa zmiennej volatie do przechowywania obiektów.

private volatile V value; 

Tak, oczywiście, jeśli masz zamiar po prostu użyć get() i set() na AtomicReference to jest jak za pomocą zmiennej zmienne. Ale, jak skomentowali inni czytelnicy, AtomicReference zapewnia dodatkową semantykę CAS. Tak więc, najpierw zdecyduj, czy chcesz semantyki CAS, czy nie, a jeśli robisz to tylko wtedy użyj AtomicReference.

+8

* "Kod źródłowy JDK jest jednym z najlepszych sposobów na odpowiedź na takie konfuzje" * => Niekoniecznie się zgadzam - javadoc (który jest kontraktem klasy) jest najlepszym sposobem. To, co znajdziesz w kodzie, odpowiada na pytanie o konkretną implementację, ale kod może się zmienić. – assylias

+3

Na przykład [this variable] (http://stackoverflow.com/a/14363501/829571) w hashmap był niestabilny w JDK 6, ale nie jest już niestabilny w Javie 7. Czy oparłeś swój kod na fakcie, że zmienna był niestabilny, zepsułby się podczas tłumaczenia JDK ... Co prawda przykład jest inny, ale masz rację. – assylias

1

Istnieje kilka różnic i kompromisów:

  1. Korzystanie się AtomicReference get/zestaw ma taką samą JMM semantykę jako pole lotnej (jako stanów javadoc), ale AtomicReference jest owinięcie wokół odniesienie, więc każdy dostęp do pola obejmuje kolejny wskaźnik pościgu.

  2. Ślad pamięci mnoży (zakładając środowiska ups skompresowane, co ma miejsce w przypadku większości maszyn wirtualnych):

    • lotny ref = 4b
    • AtomicReference = 4b + 16b (obiektu 12b nagłówek + Pole 4b ref)
  3. AtomicReference oferuje bogatszy interfejs API niż ulotne odniesienie. Możesz odzyskać API dla ulotnego odniesienia za pomocą AtomicFieldUpdater lub z Java 9 a VarHandle. Możesz także sięgnąć prosto do sun.misc.Unsafe, jeśli lubisz biegać z nożyczkami. AtomicReference samo zaimplementowane przy użyciu Unsafe.

Więc, kiedy jest dobrze, aby wybrać jeden nad drugim:

  • wystarczy get/set? Trzymaj się z lotnym polem, najprostszym rozwiązaniem i najniższym obciążeniem.
  • Potrzebujesz dodatkowej funkcjonalności? Jeśli jest to wydajność (obciążenie związane z szybkością/pamięcią), czuła część twojego kodu dokonuje wyboru między AtomicReference/AtomicFieldUpdater/Unsafe, gdzie zazwyczaj płacisz w czytelności i ryzyku wzrostu wydajności. Jeśli nie jest to obszar wrażliwy, po prostu przejdź na AtomicReference. Autorzy bibliotek zwykle używają kombinacji tych metod w zależności od wybranych JDK, oczekiwanych ograniczeń API, ograniczeń pamięci i tak dalej.
Powiązane problemy