Próbując zrozumieć, w jaki sposób SubmissionPublisher( kod źródłowy w Java SE 10, OpenJDK | docs ), nowa klasa dodana do Java SE w wersji 9, została zaimplementowana, natknąłem się na kilka wywołań API, VarHandlektórych wcześniej nie byłem świadomy:
fullFence, acquireFence, releaseFence, loadLoadFenceI storeStoreFence.
Po przeprowadzeniu pewnych badań, szczególnie w odniesieniu do koncepcji barier / płotów pamięci (słyszałem o nich wcześniej, tak; ale nigdy ich nie użyłem, a zatem nie byłem zaznajomiony z ich semantyką), myślę, że mam podstawową wiedzę na temat tego, do czego służą . Niemniej jednak, ponieważ moje pytania mogą wynikać z nieporozumień, przede wszystkim chcę się upewnić, że dobrze to zrozumiałem:
Bariery pamięci zmieniają ograniczenia dotyczące operacji odczytu i zapisu.
Bariery pamięci można podzielić na dwie główne kategorie: jednokierunkowe i dwukierunkowe bariery pamięci, w zależności od tego, czy nakładają ograniczenia na odczyty, zapisy czy oba.
C ++ obsługuje różne bariery pamięci , jednak nie pasują one do tych dostarczonych przez
VarHandle. Jednak niektóre z dostępnych barier pamięciVarHandlezapewniają efekty porządkowania, które są zgodne z odpowiadającymi im barierami pamięci C ++.#fullFencejest kompatybilny zatomic_thread_fence(memory_order_seq_cst)#acquireFencejest kompatybilny zatomic_thread_fence(memory_order_acquire)#releaseFencejest kompatybilny zatomic_thread_fence(memory_order_release)#loadLoadFencei#storeStoreFencenie mają kompatybilnej części licznika C ++
Słowo „ kompatybilny” wydaje się tutaj naprawdę ważne, ponieważ semantyka wyraźnie różni się, jeśli chodzi o szczegóły. Na przykład wszystkie bariery C ++ są dwukierunkowe, podczas gdy bariery Java nie są (koniecznie).
- Większość barier pamięci ma również efekty synchronizacji. Te w szczególności zależą od zastosowanego rodzaju bariery i wcześniej wykonanych instrukcji barier w innych wątkach. Ponieważ pełne implikacje instrukcji barierowej są specyficzne dla sprzętu, pozostanę przy barierach wyższego poziomu (C ++). Na przykład w C ++ zmiany dokonane przed instrukcją bariery zwolnienia są widoczne dla wątku wykonującego instrukcję bariery nabywania .
Czy moje założenia są prawidłowe? Jeśli tak, moje pytania wynikowe to:
Czy dostępne bariery pamięci
VarHandlepowodują jakąkolwiek synchronizację pamięci?Niezależnie od tego, czy powodują synchronizację pamięci, czy nie, jakie zmiany w ograniczaniu kolejności mogą być przydatne w Javie? Model pamięci Java daje już pewne bardzo mocne gwarancje dotyczące zamawiania przy zmiennych polach, blokadach lub
VarHandlepodobnych operacjach#compareAndSet.
Jeśli szukasz przykładu: wyżej wspomniana BufferedSubscriptionklasa wewnętrzna SubmissionPublisher(źródło połączone powyżej) ustanowiła pełne ogrodzenie w linii 1079 (funkcja growAndAdd; ponieważ połączona witryna nie obsługuje identyfikatorów fragmentów, wystarczy CTRL + F dla tego ). Nie jest jednak dla mnie jasne, do czego służy.
plain -> opaque -> release/acquire -> volatile (sequential consistency).