10

Jeśli uzyskam dostęp do obiektu wewnątrz metody zsynchronizowanej lub bloku zsynchronizowanego, czy obiekt w tym dostępnym elemencie jest również zsynchronizowany?Czy synchronizacja Java zaktualizuje całą pamięć podręczną lub tylko obiekt, na którym się zsynchronizowałem?

Imagine jest przedmiotem Queue o zsynchronizowany add() i take() metodę, przyjmowanie i przekazywanie na zewnątrz złożonego obiektu Thing. Thing ma wiele list z innymi różnymi obiektami.

Teraz wątek obrazu Before tworzy Thing i umieszcza niektóre istniejące obiekty w Thing, modyfikuje niektóre z tych obiektów i tak dalej. Wątek Before dodaje Thing do Queue. Nieco później wątek After pobiera Thing z Queue.

PYTANIE: Czy Thing i wszystkie jego dzieci/podobiekt będą w takim samym stanie, w jakim je zostawił Before? Nawet jeśli wątek After może pracował nad jedną z tych podelementów nieco wcześniej? Ponieważ obraz procesora dla wątku After może nadal zawierać pewne buforowane informacje na temat tego podelementu (adres tego obiektu podrzędnego jest wciąż taki sam). Cała ta pamięć podręczna zostanie unieważniona tylko przez zsynchronizowany dostęp do obiektu ojca Thing?

Proszę nie udzielać odpowiedzi, takich jak używanie bibliotek współbieżnych itp. Chcę zrozumieć, co się dzieje.

Odpowiedz

7

Ważną koncepcją w modelu pamięci Java jest happens-before order. Wyniki akcji zapisu, które mają miejsce: - przed czynnościami odczytu są widoczne dla tych akcji odczytu. Inne wyniki mogą być widoczne lub nie.

zdarzyć, przed celu wywołuje się przez celu synchronizacji działania pomiędzy gwintem, oraz przez naturalnego kolejności działania w poszczególnych nitek.

Jeśli wykonasz synchronizację obiektu (Before) (np.Twój Queue), a nie wszystkich manipulacji Thing i jego „podobiektów” wewnątrz lub przed tym zsynchronizowanym bloku i After zsynchronizowanych na tym samym Queue i czyta te obiekty lub po zsynchronizowanym bloku, a następnie wszystkie te zmiany są widoczne dla After.

9

Jeśli wątek modyfikuje zmienną, inny wątek nie może zobaczyć zmian, z wyjątkiem następujących przypadków (cóż, przynajmniej w następujących przypadkach: nie jestem w 100% pewny, czy jest ich więcej):

  • wątek modyfikujący pozostawia zsynchronizowany blok lub metodę; powoduje to przepełnienie pamięci podręcznej wątków (podobnie wątek, który wchodzi w zsynchronizowany blok lub metoda powoduje odświeżenie) - tak dzieje się w twoim przypadku
  • zmienna o zmiennej została zadeklarowana jako volatile lub jest jedną ze zmiennych atomowych z java.util.concurrent.atomic
  • kończy się gwint modyfikujący (ten wywołuje również kolor, podobnie początku wątku wywołuje Odśwież)

Więc jeśli synchronizować, jak wyjaśnił, inne wątki będą widzieć wszystkie zmiany.

+1

Tak, wiem o tym, ale to nie było do końca moje pytanie :-) Synchronizacja musi również wpływać na pamięci podręczne procesorów, więc zmiany są przepłukiwane do wspólnej pamięci, o to właśnie chodzi. Wiem, że jeśli uzyskasz dostęp do referencji bez przechodzenia przez zsynchronizowany blok z wielu równoległych wątków, wszystko zostanie skompromitowane. Ale chodzi bardziej o przekazywanie rzeczy z jednego wątku na drugi i zapewnienie, że datastrucuture jest nadal poprawny. Rozumiesz co mam na myśli? –

+1

Zobacz odpowiedź Paula. Blokowanie wątków jest tylko jednym aspektem synchronizacji, relacja dzieje się przedtem (opróżnianie pamięci podręcznej) jest równie ważna, jeśli nie większa. Jest to również trudniejsze do zrozumienia, a API nie jest jasne o tym, co się dzieje - wcześniej (na przykład, myślę, że SwingUtilities.invokeLater prowokuje zdarzenie przed, ale nie jestem w 100% pewny). Gorąco polecam Java Concurrency in Practice od Goetz et al. Przywiązują dużą wagę do tego, co się dzieje - wcześniej. – toto2

+0

Dzięki za zaniedbanie bez wyjaśnienia ... @Franz: Nie było dla mnie jasne, że pytasz o model pamięci. Pozwól mi przemyśleć odpowiedź. – musiKk

Powiązane problemy