AtomicInteger lazySet vs. set

Jaka jest różnica pomiędzy lazySet i set metodami AtomicInteger? Dokumentacja nie ma wiele do powiedzenia na temat lazySet:

Ostatecznie ustawia na podaną wartość.

Wydaje się, że przechowywana wartość nie zostanie natychmiast ustawiona na żądaną wartość, ale zamiast tego zostanie zaplanowana na jakiś czas w przyszłości. Ale jakie jest praktyczne zastosowanie tej metody? Jakiś przykład?

Author: David Harkness, 2009-09-23

6 answers

Cytowane prosto z "JDK-6275329: Dodaj metody lazySet do klas atomowych":

Jako prawdopodobnie ostatnia mała kontynuacja JSR166 dla Mustanga, dodaliśmy metodę "lazySet" do klas atomowych (AtomicInteger, AtomicReference, etc). To jest nisza metoda, która jest czasami przydatna podczas dostrajania kodu za pomocą nieblokujące struktury danych. Semantyka to że zapis jest gwarantowany, że nie zostanie ponownie zamówiony z żadnym poprzedni zapis, ale może być zmieniany z kolejne operacje (lub równoważnie, może nie być widoczny dla innych wątków) dopóki występuje inna zmienna akcja zapisu lub synchronizacji).

Głównym przypadkiem użycia jest nulling pól węzłów w nieblokujące struktury danych wyłącznie w celu uniknięcia długoterminowe przechowywanie śmieci; ma zastosowanie, gdy jest nieszkodliwe jeśli inne wątki przez jakiś czas widzą wartości inne niż null, ale jak zapewnić, że struktury są ostatecznie GCable. W takich sprawy, możesz być lepszy wydajność poprzez unikanie koszty null volatile-write. Jest kilka inne przypadki użycia w tym zakresie w przypadku braku odniesienia atomiki, więc metoda jest obsługiwana we wszystkich Zajęcia AtomicX.

Dla ludzi, którzy lubią myśleć o tych operacjach w kategoriach bariery na poziomie maszyny na wspólnych wieloprocesorach, lazySet stanowi barierę przed sklepem-sklepem (która jest albo no-op lub bardzo tani na obecnych platformach), ale nie Store-load barrier (co zwykle jest kosztowną częścią lotnego zapisu).

 100
Author: yawn,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-09-25 18:50:58

LazySet może być używany do komunikacji między wątkami rmw, ponieważ xchg jest atomowy, co do widoczności, gdy proces wątku Writera zmodyfikuje lokalizację linii pamięci podręcznej, procesor wątku czytnika zobaczy go przy następnym odczycie, ponieważ protokół spójności pamięci podręcznej procesora intel będzie działał lazyset, ale linia pamięci podręcznej zostanie zaktualizowana przy następnym odczycie, ponownie, procesor musi być wystarczająco nowoczesny.

Http://sc.tamu.edu/systems/eos/nehalem.pdf Dla Nehalem, który jest wieloprocesorowym Platforma, procesory mają możliwość "podsłuchiwania" (podsłuchiwania) magistrali adresowej dla innych procesorów dostępu do pamięci systemowej i ich wewnętrznych pamięci podręcznych. Wykorzystują tę zdolność szpiegowania, aby utrzymać wewnętrzną pamięć podręczną spójną zarówno z pamięcią systemową, jak i z pamięcią podręczną w innych połączonych procesorach. Jeśli poprzez Szpiegowanie jeden procesor wykryje, że inny procesor zamierza zapisać do miejsca pamięci, które obecnie jest buforowane w stanie współdzielonym, procesor szpiegujący unieważni blok pamięci podręcznej zmusza go do wypełnienia linii pamięci podręcznej następnym razem, gdy uzyska dostęp do tej samej lokalizacji pamięci.

Oracle hotspot jdk for x86 cpu architecture - >

LazySet = = putOrderedLong = = xchg rw( Instrukcja asm służąca jako soft barrier kosztująca 20 cykli na procesorze nehelem intel)

Na x86 (x86_64) taka bariera jest znacznie tańsza pod względem wydajności niż volatile czy AtomicLong getAndAdd,

In an one producer, one consumer queue scenario, xchg soft bariera może wymusić linię kodów przed zestawem lazySet (Sekwencja+1), aby wątek producenta miał miejsce przed dowolnym kodem wątku konsumenckiego, który pochłonie (pracuje nad) nowe dane, oczywiście wątek konsumencki będzie musiał sprawdzić atomicznie, że sekwencja producenta została zwiększona o dokładnie jeden przy użyciu zestawu compareAndSet (Sekwencja, Sekwencja + 1).

Śledziłem kod źródłowy hotspota, aby znaleźć dokładne odwzorowanie lazySet do cpp kod: http://hg.openjdk.java.net/jdk7/jdk7/hotspot/file/9b0ca45cd756/src/share/vm/prims/unsafe.cpp Unsafe_setOrderedLong -> set_field_volatile definition - > OrderAccess:release_store_fence. Dla x86_64, OrderAccess: release_store_fence jest zdefiniowany jako za pomocą instrukcji xchg.

Możesz zobaczyć jak to jest dokładnie zdefiniowane w jdk7 (doug lea pracuje nad kilkoma nowymi rzeczami dla JDK 8): http://hg.openjdk.java.net/jdk7/jdk7/hotspot/file/4fc084dac61e/src/os_cpu/linux_x86/vm/orderAccess_linux_x86.inline.hpp

Możesz również użyć hdis do demontażu zestawu kodu lazySet w akcji.

Jest jeszcze jedno powiązane pytanie: Czy potrzebujemy mfence podczas korzystania z xchg

 13
Author: porkchop,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:10:33

Szersze omówienie genezy i użyteczności lazySet i podstawowego putOrdered można znaleźć tutaj: http://psy-lob-saw.blogspot.co.uk/2012/12/atomiclazyset-is-performance-win-for.html

Podsumowując: lazySet jest słabym lotnym zapisem w tym sensie, że działa jako Store-store, a nie ogrodzenie store-load. To sprowadza się do tego, że lazySet jest kompilowany do instrukcji MOV, która nie może być ponownie zamówiona przez kompilator, a nie znacznie droższy Instrukcja używana dla zestawu lotnego.

Podczas odczytu wartości zawsze kończysz na odczycie zmiennym (z atomowym*.get() w każdym razie).

LazySet oferuje pojedynczemu pisarzowi spójny mechanizm zmiennego zapisu, tzn. jest całkowicie uzasadnione, aby pojedynczy pisarz używał lazySet do zwiększania licznika, wiele wątków zwiększających ten sam licznik będzie musiało rozwiązać konkurencyjne zapisy za pomocą CAS, co dokładnie dzieje się pod osłoną Atomic* dla incAndGet.

 9
Author: Nitsan Wakart,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-12-24 11:42:44

From the Concurrent-atomic package summary

LazySet ma efekt zapisu (przypisywania) zmiennej volatile, z wyjątkiem tego, że pozwala na zmianę kolejności z kolejnymi (ale nie poprzednimi) akcjami pamięci, które same w sobie nie nakładają ograniczeń zmiany kolejności przy zwykłych zapisach nieulotnych. Wśród innych kontekstów użytkowania, lazySet może mieć zastosowanie, gdy anuluje, ze względu na zbieranie śmieci, odniesienie, które nigdy nie jest dostępne.

Jeśli jesteś ciekawi mnie lazySet, to też jesteś sobie winien inne wyjaśnienia

Efekty pamięci dla dostępu i aktualizacji atomiki ogólnie postępuj zgodnie z zasadami określonymi w sekcji 17.4 Java™ Specyfikacja Języka.

Get ma efekt pamięci odczytu zmiennej zmiennej.

Set {[6] } ma efekty pamięci zapisu (przypisywania) zmiennej zmiennej.

LazySet ma efekt pamięci zapisu (przypisywanie) zmiennej zmiennej z tą różnicą, że pozwala na zmianę kolejności z kolejnymi (ale nie poprzednimi) akcjami pamięci, które same nie narzucają zmiany kolejności ograniczenia ze zwykłymi nieulotnymi zapisami. Wśród innych zastosowań konteksty, lazySet może mieć zastosowanie w przypadku anulowania, ze względu na śmieci kolekcja, odniesienie, które nigdy nie jest dostępne ponownie.

WeakCompareAndSet atomicznie odczytuje i warunkowo zapisuje zmienną, ale nie tworzy żadnych happens-przed zamówieniem, tak zapewnia brak gwarancji w odniesieniu do poprzednich lub późniejszych odczytów i zapisów wszystkich zmiennych innych niż cel zestawu weakCompareAndSet. compareAndSet i wszystkie inne operacje odczytu i aktualizacji, takie jak getAndIncrement, mają efekty pamięci zarówno odczytu, jak i zapisu zmienne zmienne.

 6
Author: Ajeet Ganga,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-11-08 10:31:58

Oto moje zrozumienie, popraw mnie, jeśli się mylę: Możesz myśleć o lazySet() jako "semi" volatile: jest to w zasadzie nieulotna zmienna pod względem odczytu przez inne wątki, tzn. wartość ustawiona przez lazySet może nie być widoczna dla innych wątków. Ale staje się niestabilny, gdy występuje kolejna operacja zapisu (może być z innych wątków). Jedyny wpływ lazySet mogę sobie wyobrazić compareAndSet. Więc jeśli używasz lazySet(), get() z innych wątków może nadal uzyskać starą wartość, ale compareAndSet() zawsze będzie miał nowa wartość, ponieważ jest to operacja zapisu.

 3
Author: jyluo,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-08-21 10:51:55

[0] Re: próba osłupienia -

Możesz myśleć o tym jako o sposobie traktowania pola lotnego tak, jakby nie było ono lotne dla konkretnego sklepu (np.: ref = null;).

To nie jest do końca dokładne, ale powinno wystarczyć, abyś mógł podjąć decyzję między "OK, naprawdę mnie to nie obchodzi" i "Hmm, pozwól mi to przemyśleć".

 2
Author: Paul Mclachlan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-04-23 21:20:59