Czy ktoś może mi powiedzieć przewagę metody zsynchronizowanej nad zsynchronizowanym blokiem z przykładem?
java
multithreading
concurrency
locking
synchronized
Wojownik
źródło
źródło
Odpowiedzi:
Nie ma wyraźnej przewagi przy użyciu metody synchronicznej nad blokiem.
Być może jedynym (ale nie nazwałbym tego zaletą) jest to, że nie musisz dołączać odwołania do obiektu
this
.Metoda:
Blok:
Widzieć? Żadnej przewagi.
Bloki nie mają przewagę nad metodami choć przeważnie elastyczność, ponieważ można użyć innego obiektu jako zamka podczas synchronizowania metody by zablokować cały obiekt.
Porównać:
vs.
Ponadto, jeśli metoda rośnie, nadal możesz rozdzielić zsynchronizowaną sekcję:
źródło
synchronized
Blok jest realizowany za pomocą dwóch instrukcji,monitorenter
imonitorexit
, oraz obsługę wyjątków, które gwarantuje, żemonitorexit
nazywa się nawet w wyjątkowych przypadkach. To wszystko jest zapisywane podczas korzystania zsynchronized
metody.Jedyną prawdziwą różnicą jest to, że zsynchronizowany blok może wybrać obiekt, na którym ma być synchronizowany. Zsynchronizowana metoda może używać tylko
'this'
(lub odpowiedniej instancji klasy dla zsynchronizowanej metody klasy). Na przykład są one semantycznie równoważne:Ten ostatni jest bardziej elastyczny, ponieważ może konkurować o skojarzoną blokadę dowolnego obiektu, często zmiennej elementu. Jest to również bardziej szczegółowe, ponieważ możesz mieć współbieżny kod wykonywany przed i po bloku, ale nadal w ramach metody. Oczywiście równie łatwo można zastosować metodę zsynchronizowaną, przekształcając współbieżny kod w osobne niezsynchronizowane metody. Użyj tego, co czyni kod bardziej zrozumiałym.
źródło
Metoda synchroniczna
Plusy:
Cons:
Zsynchronizowany blok
Plusy:
Cons:
Osobiście wolę używać metod zsynchronizowanych z klasami skoncentrowanymi tylko na rzeczach wymagających synchronizacji. Taka klasa powinna być tak mała, jak to możliwe, a więc powinna być łatwa przegląd synchronizacji. Inni nie powinni się przejmować synchronizacją.
źródło
Główna różnica polega na tym, że jeśli korzystasz ze zsynchronizowanego bloku, możesz zablokować obiekt inny niż ten co pozwala być bardziej elastycznym.
Załóżmy, że masz kolejkę komunikatów oraz wielu producentów i konsumentów wiadomości. Nie chcemy, aby producenci przeszkadzali sobie nawzajem, ale konsumenci powinni mieć możliwość wyszukiwania wiadomości bez konieczności oczekiwania na producentów. Więc po prostu tworzymy obiekt
I odtąd za każdym razem, gdy producent chce dodać nową wiadomość, po prostu to blokujemy:
Tak więc konsumenci mogą nadal czytać, a producenci zostaną zablokowani.
źródło
Metoda zsynchronizowana
Zsynchronizowane metody mają dwa efekty.
Po pierwsze, gdy jeden wątek wykonuje zsynchronizowaną metodę dla obiektu, wszystkie inne wątki, które wywołują metody zsynchronizowane dla tego samego bloku obiektu (zawieszają wykonywanie), dopóki pierwszy wątek nie zostanie zakończony z obiektem.
Po drugie, kiedy zsynchronizowana metoda kończy działanie, automatycznie ustanawia relację przed zdarzeniem z każdym kolejnym wywołaniem zsynchronizowanej metody dla tego samego obiektu. Gwarantuje to, że zmiany stanu obiektu są widoczne dla wszystkich wątków.
Pamiętaj, że konstruktory nie mogą być synchronizowane - użycie słowa kluczowego synchronizowanego z konstruktorem jest błędem składni. Synchronizacja konstruktorów nie ma sensu, ponieważ tylko wątek, który tworzy obiekt, powinien mieć do niego dostęp podczas jego konstruowania.
Instrukcja zsynchronizowana
W przeciwieństwie do metod zsynchronizowanych, instrukcje zsynchronizowane muszą określać obiekt, który zapewnia wewnętrzną blokadę: Najczęściej używam tego do synchronizowania dostępu do listy lub mapy, ale nie chcę blokować dostępu do wszystkich metod obiektu.
P: Wewnętrzne blokady i synchronizacja Synchronizacja opiera się na wewnętrznej jednostce znanej jako wewnętrzna blokada lub blokada monitora. (Specyfikacja API często odnosi się do tego bytu po prostu jako „monitor”). Zamki wewnętrzne odgrywają rolę w obu aspektach synchronizacji: wymuszając wyłączny dostęp do stanu obiektu i ustanawiając relacje, które są istotne dla widoczności.
Z każdym obiektem jest związana wewnętrzna blokada. Zgodnie z konwencją wątek, który wymaga wyłącznego i spójnego dostępu do pól obiektu, musi uzyskać wewnętrzną blokadę obiektu przed uzyskaniem do nich dostępu, a następnie zwolnić blokadę wewnętrzną, gdy jest to zrobione. Mówi się, że wątek jest właścicielem wewnętrznego zamka między momentem, w którym zamek uzyskał i zwolnił zamek. Tak długo, jak wątek posiada wewnętrzny zamek, żaden inny wątek nie może uzyskać tego samego zamka. Drugi wątek zostanie zablokowany podczas próby uzyskania blokady.
Sprawdź krzyżowo różne wyjścia metodą zsynchronizowaną, blokuj i bez synchronizacji.
źródło
Uwaga: statyczne metody synchronizacji i bloki działają na obiekcie klasy.
źródło
Kiedy kompilator Java konwertuje kod źródłowy na kod bajtowy, bardzo zróznicuje metody synchronizowane i bloki zsynchronizowane.
Gdy JVM wykonuje metodę zsynchronizowaną, wątek wykonujący stwierdza, że struktura metody method_info metody ma ustawioną flagę ACC_SYNCHRONIZED, a następnie automatycznie uzyskuje blokadę obiektu, wywołuje metodę i zwalnia blokadę. Jeśli wystąpi wyjątek, nić automatycznie zwalnia blokadę.
Z drugiej strony synchronizacja bloku metod pomija wbudowaną obsługę JVM w zakresie uzyskiwania blokady obiektu i obsługi wyjątków i wymaga jawnego zapisania tej funkcji w kodzie bajtowym. Jeśli przeczytasz kod bajtu dla metody ze zsynchronizowanym blokiem, zobaczysz kilkanaście dodatkowych operacji w celu zarządzania tą funkcjonalnością.
To pokazuje wywołania w celu wygenerowania zarówno metody zsynchronizowanej, jak i zsynchronizowanego bloku:
synchronizedMethodGet()
Sposób wytwarza się następujące kod binarny:A oto kod bajtu z
synchronizedBlockGet()
metody:Jedną znaczącą różnicą między metodą zsynchronizowaną a blokiem jest to, że Zsynchronizowany blok ogólnie zmniejsza zakres blokady. Ponieważ zakres blokady jest odwrotnie proporcjonalny do wydajności, zawsze lepiej jest zablokować tylko krytyczną sekcję kodu. Jednym z najlepszych przykładów użycia bloku synchronicznego jest podwójne sprawdzanie blokowania we wzorze Singleton, gdzie zamiast blokowania całej
getInstance()
metody blokujemy tylko krytyczną sekcję kodu, która jest używana do utworzenia instancji Singleton. Znacząco poprawia to wydajność, ponieważ blokowanie jest wymagane tylko jeden lub dwa razy.Podczas korzystania z metod zsynchronizowanych należy zachować szczególną ostrożność, jeśli łączysz zarówno metody zsynchronizowane statycznie, jak i niestatyczne.
źródło
monitorenter
imonitorexit
przed uruchomieniem kodu.Najczęściej używam tego do synchronizacji dostępu do listy lub mapy, ale nie chcę blokować dostępu do wszystkich metod obiektu.
W poniższym kodzie jeden wątek modyfikujący listę nie będzie blokował oczekiwania na wątek modyfikujący mapę. Jeśli metody zostały zsynchronizowane z obiektem, każda metoda musiałaby poczekać, nawet jeśli wprowadzane modyfikacje nie kolidowałyby.
źródło
Dzięki zsynchronizowanym blokom możesz mieć wiele synchronizatorów, dzięki czemu może jednocześnie działać wiele jednoczesnych, ale nie powodujących konfliktu rzeczy.
źródło
Zsynchronizowane metody można sprawdzić za pomocą refleksyjnego interfejsu API. Może to być przydatne do testowania niektórych umów, takich jak synchronizacja wszystkich metod w modelu .
Poniższy fragment wypisuje wszystkie zsynchronizowane metody Hashtable:
źródło
Ważna uwaga na temat korzystania z synchronizowanego bloku: uważaj, czego używasz jako obiektu blokady!
Fragment kodu z powyższego user2277816 ilustruje ten punkt, w którym odwołanie do literału łańcucha jest używane jako obiekt blokujący. Zdaj sobie sprawę z tego, że literały łańcuchowe są automatycznie internowane w Javie i powinieneś zacząć dostrzegać problem: każdy fragment kodu, który synchronizuje się na dosłownie „blokadzie”, ma tę samą blokadę! Może to łatwo doprowadzić do impasu przy całkowicie niepowiązanych fragmentach kodu.
Nie chodzi tylko o obiekty String, na które trzeba uważać. Prymitywy w pudełkach są również niebezpieczne, ponieważ metody autoboxowania i metody valueOf mogą ponownie wykorzystywać te same obiekty, w zależności od wartości.
Aby uzyskać więcej informacji, zobacz: https://www.securecoding.cert.org/confluence/display/java/LCK01-J.+Do+not+synchronize+on+objects+that+may+be+reused
źródło
Często używanie blokady na poziomie metody jest zbyt niegrzeczne. Po co blokować fragment kodu, który nie ma dostępu do żadnych udostępnionych zasobów, blokując całą metodę. Ponieważ każdy obiekt ma blokadę, można tworzyć fikcyjne obiekty w celu wdrożenia synchronizacji na poziomie bloku. Poziom bloku jest bardziej wydajny, ponieważ nie blokuje całej metody.
Oto przykład
Poziom metody
Poziom bloku
[Edytować]
Dla
Collection
jakVector
iHashtable
oni są zsynchronizowane, gdyArrayList
alboHashMap
nie są i muszą Państwo ustawić zsynchronizowane słowa kluczowego lub invoke Collections zsynchronizowany sposób:źródło
Jedyna różnica: zsynchronizowane bloki pozwalają na precyzyjne blokowanie w przeciwieństwie do metody zsynchronizowanej
Gruntownie
synchronized
blok lub metody do pisania bezpiecznego kodu wątku, unikając błędów niespójności pamięci.To pytanie jest bardzo stare i wiele rzeczy zostało zmienionych w ciągu ostatnich 7 lat. Wprowadzono nowe konstrukcje programistyczne dla bezpieczeństwa wątków.
Bezpieczeństwo wątków można osiągnąć, używając zaawansowanego interfejsu API współbieżności zamiast
synchronied
bloków. Ta strona dokumentacji zawiera dobre konstrukcje programistyczne do osiągnięcia bezpieczeństwa wątków.Zablokuj obiekty obsługują idiomy blokujące, które upraszczają wiele jednoczesnych aplikacji.
Wykonawcy definiują interfejs API wysokiego poziomu do uruchamiania wątków i zarządzania nimi. Implementacje executorów dostarczone przez java.util.concurrent zapewniają zarządzanie pulą wątków odpowiednie dla aplikacji na dużą skalę.
Współbieżne kolekcje ułatwiają zarządzanie dużymi zbiorami danych i mogą znacznie zmniejszyć potrzebę synchronizacji.
Zmienne atomowe mają funkcje minimalizujące synchronizację i pomagające uniknąć błędów spójności pamięci.
ThreadLocalRandom (w JDK 7) zapewnia wydajne generowanie liczb pseudolosowych z wielu wątków.
Lepszym zamiennikiem synchronizowanego jest ReentrantLock , który korzysta z
Lock
APIPrzykład z zamkami:
Zapoznaj się także z pakietami java.util.concurrent i java.util.concurrent.atomic, aby zapoznać się z innymi konstrukcjami programistycznymi.
Zobacz także podobne pytanie:
Synchronizacja vs Blokada
źródło
Metoda synchronizacji służy do blokowania wszystkich obiektów Blok synchronizacji służy do blokowania określonych obiektów
źródło
Zasadniczo są to w większości te same, inne niż jawne informacje na temat monitora obiektu, który jest używany, w porównaniu z niejawnym obiektem. Jedną wadą zsynchronizowanych metod, które moim zdaniem są czasami pomijane, jest to, że używając odniesienia „to” do synchronizacji na sobie, pozostawiasz otwartą możliwość blokowania obiektów zewnętrznych na tym samym obiekcie. To może być bardzo subtelny błąd, jeśli na niego wpadniesz. Synchronizacja na wewnętrznym jawnym obiekcie lub innym istniejącym polu może uniknąć tego problemu, całkowicie obudowując synchronizację.
źródło
Jak już powiedziano tutaj, zsynchronizowany blok może wykorzystywać zmienną zdefiniowaną przez użytkownika jako obiekt blokady, gdy funkcja synchronizacji używa tylko „tego”. I oczywiście możesz manipulować obszarami swojej funkcji, które powinny być zsynchronizowane. Ale wszyscy mówią, że nie ma różnicy między funkcją zsynchronizowaną a blokiem, który obejmuje całą funkcję, używając „tego” jako obiektu blokady. To nieprawda, różnica polega na kodzie bajtów, który zostanie wygenerowany w obu sytuacjach. W przypadku użycia bloku zsynchronizowanego należy przypisać zmienną lokalną, która zawiera odniesienie do „tego”. W rezultacie będziemy mieli nieco większy rozmiar funkcji (nie dotyczy, jeśli masz tylko kilka funkcji).
Bardziej szczegółowe wyjaśnienie różnicy można znaleźć tutaj: http://www.artima.com/insidejvm/ed2/threadsynchP.html
źródło
W przypadku metod zsynchronizowanych blokada zostanie uzyskana na obiekcie. Ale jeśli wybierzesz synchronizowany blok, masz opcję określenia obiektu, na którym zostanie uzyskana blokada.
Przykład:
źródło
Wiem, że to stare pytanie, ale po szybkim przeczytaniu tutaj odpowiedzi tak naprawdę nie zauważyłem, aby ktokolwiek wspomniał, że czasami
synchronized
metoda może być niewłaściwą blokadą.Z Java Concurrency In Practice (str. 72):
Powyższy kod ma wygląd bycia wątku bezpieczny. Jednak w rzeczywistości tak nie jest. W takim przypadku blokada jest uzyskiwana na instancji klasy. Możliwe jest jednak zmodyfikowanie listy przez inny wątek, który nie korzysta z tej metody. Prawidłowe podejście byłoby użyć
Powyższy kod blokowałby wszystkie wątki próbujące zmodyfikować listę przed modyfikowaniem listy, dopóki synchronizowany blok nie zostanie zakończony.
źródło
List
może prowadzić do problemów z wydajnością, jeśli istnieje dziennik kodu, który niekoniecznie musi być synchronizowanyW praktyce przewaga metod zsynchronizowanych nad zsynchronizowanymi blokami polega na tym, że są one bardziej odporne na idioty; ponieważ nie można wybrać dowolnego obiektu do zablokowania, nie można niewłaściwie używać składni metody synchronicznej do robienia głupich rzeczy, takich jak blokowanie literału łańcucha lub blokowanie zawartości pola zmiennego, które jest zmieniane spod wątków.
Z drugiej strony dzięki metodom zsynchronizowanym nie można zabezpieczyć zamka przed zdobyciem przez dowolny wątek, który może uzyskać odwołanie do obiektu.
Dlatego użycie synchronizacji jako modyfikatora metod lepiej chroni twoich krów-orków przed samookaleczeniem, podczas gdy używanie synchronizowanych bloków w połączeniu z prywatnymi obiektami ostatecznej blokady lepiej chroni twój kod przed krowimi orkami.
źródło
Ze streszczenia specyfikacji Java: http://www.cs.cornell.edu/andru/javaspec/17.doc.html
Opierając się na tych opisach, powiedziałbym, że większość poprzednich odpowiedzi jest poprawna, a metoda zsynchronizowana może być szczególnie przydatna w przypadku metod statycznych, w których w innym przypadku musiałbyś dowiedzieć się, jak uzyskać „obiekt klasy reprezentujący klasę, w której metoda była zdefiniowane ”.
Edycja: pierwotnie myślałem, że były to cytaty rzeczywistej specyfikacji Java. Wyjaśniono, że ta strona jest jedynie streszczeniem / wyjaśnieniem specyfikacji
źródło
TLDR; Nie należy używać
synchronized
modyfikatora anisynchronized(this){...}
wyrażenia, alesynchronized(myLock){...}
gdziemyLock
jest pole ostatniej instancji zawierające prywatny obiekt.Różnica między użyciem
synchronized
modyfikatora w deklaracji metody asynchronized(..){ }
wyrażeniem w treści metody jest następująca:synchronized
Modyfikator podany na podpis metody badaniemsynchronized(this) { .... }
ithis
obiektu jako blokady, gdy jest zadeklarowany w metodzie niestatycznej lub klasy obejmującej, gdy jest zadeklarowany w metodzie statycznej.synchronized(...){...}
Ekspresja pozwalaJednak za pomocą
synchronized
modyfikatora lub zasynchronized(...) {...}
pomocąthis
jako obiektu blokady (jak wsynchronized(this) {...}
) ma tę samą wadę. Oba używają własnej instancji jako obiektu blokady do synchronizacji. Jest to niebezpieczne, ponieważ nie tylko sam obiekt, ale każdy inny zewnętrzny obiekt / kod, który zawiera odniesienie do tego obiektu, może również używać go jako blokady synchronizacji z potencjalnie poważnymi skutkami ubocznymi (obniżenie wydajności i zakleszczenia ).Dlatego najlepszą praktyką jest, aby nie używać
synchronized
modyfikatora anisynchronized(...)
wyrażenia w połączeniu zthis
obiektem blokady, ale obiektem blokady prywatnym dla tego obiektu. Na przykład:Możesz także użyć wielu obiektów zamków, ale należy zachować szczególną ostrożność, aby nie zagnieździły się, gdy zostaną zagnieżdżone.
źródło
Podejrzewam, że to pytanie dotyczy różnicy między inicjacją Sing Safeon wątku a inicjacją Lazy z blokowaniem Double Check . Zawsze odnoszę się do tego artykułu, gdy muszę wdrożyć jakiś konkretny singleton.
Cóż, to jest Singleton bezpieczny dla wątków :
To jest Leniwa inicjalizacja z blokowaniem Double Check :
Więcej informacji można znaleźć w tym artykule:
https://www.geeksforgeeks.org/java-singleton-design-pattern-practices-examples/
źródło
Synchronizacja z wątkami. 1) NIGDY nie używaj synchronizacji (tego) w wątku, który nie działa. Synchronizacja z (this) wykorzystuje bieżący wątek jako obiekt wątku blokującego. Ponieważ każdy wątek jest niezależny od innych wątków, nie ma koordynacji synchronizacji. 2) Testy kodu pokazują, że w Javie 1.6 na Macu synchronizacja metod nie działa. 3) zsynchronizowane (lockObj), gdzie lockObj jest wspólnym wspólnym obiektem wszystkich wątków synchronizujących na nim będzie działać. 4) Działa ReenterantLock.lock () i .unlock (). Zobacz samouczki Java na ten temat.
Poniższy kod pokazuje te punkty. Zawiera również bezpieczny wątek Vector, który zostałby zastąpiony ArrayList, aby pokazać, że wiele wątków dodających do Vector nie traci żadnych informacji, podczas gdy to samo z ArrayList może utracić informacje. 0) Aktualny kod pokazuje utratę informacji z powodu warunków wyścigu A) Skomentuj bieżącą linię A i odkomentuj linię A nad nią, a następnie uruchom, metoda traci dane, ale nie powinna. B) Odwróć krok A, odkomentuj B i // blok końcowy}. Następnie uruchom, aby zobaczyć wyniki bez utraty danych C) Skomentuj B, odkomentuj C. Uruchom, patrz synchronizacja (to) traci dane, zgodnie z oczekiwaniami. Nie mam czasu na ukończenie wszystkich odmian, mam nadzieję, że to pomoże. Jeśli synchronizacja jest włączona (ta) lub metoda synchronizacji działa, proszę podać, którą wersję Java i systemu operacyjnego przetestowałeś. Dziękuję Ci.
źródło