2015-09-28 13 views
9

Czytałem ten answer w końcu z których następujące napisane:preferując zsynchronizowane z lotnym

Wszystko, co można z lotnym można zrobić z zsynchronizowane, ale nie odwrotnie.

Nie jest jasne. JLS 8.3.1.4 definiuje pola lotnych następująco:

Pole może być uznana za lotny, w którym to przypadku Java pamięci model zapewnia, że ​​wszystkie wątki zobaczyć spójne wartość dla zmiennej (§17.4).

Tak więc, zmienne pola dotyczą widoczności pamięci. Ponadto, o ile dostałem odpowiedzi, którą cytowałem, czytanie i pisanie na zmienne pola są zsynchronizowane.

Synchronizacja gwarantuje, że tylko jeden wątek ma dostęp do zsynchronizowanego bloku. Jak mam, nie ma to nic wspólnego z widocznością pamięci. Co mnie ominęło?

+0

Wejście i wyjście z bloku "zsynchronizowanego" wykonuje barierę pamięci, zapewniając, że zmiany są widoczne w wątkach. – Sneftel

Odpowiedz

6

W rzeczywistości synchronizacji dotyczy również widoczność pola pamięci a JVM dodaje pamięci bariery na wyjściu bloku zsynchronizowanego. Gwarantuje to, że wyniki zapisywania przez wątek w bloku synchronizacji są gwarantowane jako widoczne przez kolejne wątki po tym, jak pierwszy wątek opuścił zsynchronizowany blok.

Uwaga: następujące @ komentarzu PaŭloEbermann, w przypadku, gdy druga nitka przejść przez barierę pamięci odczytu (dostając w zsynchronizowany bloku na przykład), ich lokalny cache nie zostaną unieważnione, a zatem mogą odczytać starą wartość.

wyjściu z bloku zsynchronizowanego jest dzieje, zanim w tym dokumencie: http://docs.oracle.com/javase/6/docs/api/java/util/concurrent/package-summary.html#MemoryVisibility

szukać tych ekstraktów:

Wyniki zapisu według jednego wątku są gwarantowane być widoczne dla innego wątku tylko wtedy, gdy operacja zapisu ma miejsce - przed operacją odczytu .

i

odblokowujący (zsynchronizowane wyjście bloku lub metoda) monitora stanie, przed każdym kolejnym zamka (synchronizacji bloku lub metoda wpis) w tym samym monitorze.Ponieważ przechodzenie do stanu sprzed jest przechodnie, wszystkie działania wątku przed odblokowaniem stają się ważne - przed wszystkimi działaniami po każdym zablokowaniu wątku, które monitoruje.

+0

Doskonała odpowiedź, dziękuję bardzo. Nie sądziłem, że pod pojęciem widoczności pamięci istnieje bardziej ogólna koncepcja. –

+0

Rozumiałbym to nieco inaczej: zmiany w (i faktycznie także przed) bloku synchronizacji są widoczne tylko dla innych wątków, które następnie synchronizują się na tym samym obiekcie (lub mają jakiś inny sposób bycia w relacji "dzieje się po") , nie wszystkim czytanym przez wszystkie inne wątki. –

+0

@ PaŭloEbermann rzeczywiście, jeśli inne wątki nie synchronizują (lub nie są w żaden sposób barierą odczytu), ich lokalna pamięć podręczna nie zostanie unieważniona i dlatego może odczytać starą wartość. –

1

To źle. Synchronizacja ma związek z widocznością pamięci. Każdy wątek ma własną pamięć podręczną. Jeśli masz blokadę, pamięć podręczna jest ponownie sprawdzana. Po zwolnieniu blokady pamięć podręczna zostanie przeniesiona do pamięci głównej.

Jeśli czytasz zmienne pole, jest też odświeżanie, jeśli napiszesz zmienne pole, pojawi się kolor.

2

Zsynchronizowane i zmienne są różne, ale zazwyczaj obie są używane do rozwiązania tego samego powszechnego problemu.

Synchronizacja polega na upewnieniu się, że tylko jeden wątek uzyska dostęp do zasobu udostępnionego w określonym momencie.

Podczas gdy te zasoby wspólne są często deklarowane jako zmienne, dzieje się tak dlatego, że jeśli wątek zmienił wartość udostępnionego zasobu, musi również zostać zaktualizowany w drugim wątku. Ale bez niestabilności środowisko wykonawcze optymalizuje kod, odczytując wartość z pamięci podręcznej. Więc, co jest niestabilne, ilekroć jakikolwiek dostęp do wątku jest niestabilny, nie odczyta wartości z pamięci podręcznej, zamiast tego faktycznie pobiera ją z pamięci rzeczywistej i używa się tego samego.


Przechodzę przez kod log4j i to jest to, co znalazłem.

/** 
* Config should be consistent across threads. 
*/ 
protected volatile PrivateConfig config; 
+0

Dlaczego więc w ogóle używać słowa kluczowego "volatile", możesz uzyskać dostęp wielowątkowy bez określania lotności lub synchronizacji –

1

Jeżeli wiele wątków napisać do wspólnej zmiennej ulotnej i oni także muszą stosować poprzednią wartość niego, może to stworzyć race condition. W tym momencie potrzebujesz synchronizacji.

... jeśli dwa wątki są zarówno odczyt i zapis do zmiennej współdzielonej, a następnie za pomocą słowa kluczowego lotnych na to nie wystarczy. Musisz użyć zsynchronizowanego w tym przypadku, aby zagwarantować, że odczytywanie i zapisywanie zmiennej jest atomowe. Odczytywanie lub zapisywanie zmiennej lotnej nie blokuje czytania ani pisania nici. Aby tak się stało, musisz użyć zsynchronizowanego słowa kluczowego wokół krytycznych sekcji.

Szczegółowe tutorialu o lotnych, patrz 'volatile' is not always enough.

+1

Dla prostych przypadków, takich jak licznik bezpieczny dla wątków lub cas, użycie [Atomic] (http://docs.oracle. com/javase/7/docs/api/java/util/concurrent/atomic/package-summary.html) jest zwykle łatwiejszy i działa lepiej niż blok "zsynchronizowany", zwłaszcza przy dużej rywalizacji. – duckstep

Powiązane problemy