Pytanie wydaje się być częściowo odpowiedział tej odpowiedzi:
Java multi-threading & Safe Publication
przynajmniej jeśli chodzi o „bezpiecznej publikacji”.
Teraz, jeśli wywołujący odrzuci swoje odwołanie, zmienna będzie bezpieczna, ponieważ nie istnieje odwołanie do zmiennej z wyjątkiem końcowej zmiennej lokalnej.
Co do przykładów kodu - w moich oczach oba fragmenty kodu są równoważne. Wprowadzenie dodatkowej zmiennej lokalnej nie zmienia semantyki, w obu przypadkach kompilator rozpoznaje odwołanie jako niezmienne i pozwala z nim przejść.
EDIT - Wyjeżdżam tej części udokumentować moje błędnej interpretacji kwestii PO za
Dla wyjaśnienia - Biorę wykorzystanie final
lub volatile
jak przyznano w tym przykładzie, więc właściwe wyżywienie bariera pamięci dla widoczności Odniesienie do obiektu jest tam, jedynym punktem jest możliwa zmienność obiektu, który nie jest bezpieczny dla wątków, którego nie można zagwarantować za pomocą barier pamięciowych i faktycznie nie ma z nimi nic wspólnego. Można to zająć poprzez odpowiednią synchronizację lub pozostawienie tylko jednego odniesienia do treści.
EDIT2 - po przeczytaniu komentarzy PO za
Właśnie spojrzał na JSR 133 FAQ - AFAIU bezpieczne publikacja odniesienia do obiektu przy użyciu bariera pamięci nie gwarantuje, że unsychronized dziedzinach wymienionych odwoływać obiekt jest również widoczny. Ani przez final
ani volatile
.
jeśli nie jestem misinterpreting to nas tylko Synchronizacja na tym samym monitorze definiuje „zdarza się, zanim” związek na wszystkie się pisze jeden wątek przedtem zwolnieniu blokady synchronizacji i pozyskiwania blokadę na tym samym monitorze przez inny wątek .
Mogę się pomylić, ale brzmi to tak, jakby były również niezsynchronizowane pola obiektu odniesienia.
przypadku korzystania final
słowa kluczowego (jak w przykładzie, w którym parametr zostanie wstawiony jako pole final
) - tylko pól instancji odwołanie obiektu, które same są final
są gwarancją widoczne po wybudowaniu obiektu kończy.
Ale w BlockingQueue
(oraz jego implementacji, LinkedBlockingQueue
) nie widzę synchronized
słowa kluczowego w ogóle - wydaje się, że używa jakiś bardzo mądry kod do wdrożenia synchronizacji za pomocą volatile
pól, dla mnie to nie brzmi jak synchronizacja na monitorze w znaczeniu opisanym w JSR 133.
Co oznacza, że zwykłe kolejki blokujące używane przez Executora nie gwarantują widoczności nieostatnich pól instancji Unsafe
. Chociaż samo odwołanie może być bezpiecznie opublikowane przy użyciu tylko słowa kluczowego final
, bezpieczne publikowanie pól, do których odnosi się ten punkt odniesienia, wymaga również, aby pola były również final
lub synchronizacji z monitorem udostępnionym przez program piszący i czytnik.
Nie strzelaj do posłańca :-).
Twój executor używa kolejki wątków bezpiecznych. Aby zobaczyć ten problem, musisz przekazać obiekt między wątkami bez użycia odpowiednich barier pamięci w dowolnym miejscu. –
@PeterLawrey 'class Executor {void execute (Runnable r) {}}' - brak kolejki tutaj. Ale kwestia jest * prawdopodobnie * ważna, mimo to ... – Marco13
BTW 'Unsafe' to klasa, która ma singleton, chociaż możesz stworzyć ich więcej ... –