Zastanawiam się, który z nich jest lepszy w praktyce i dlaczego?
Odkryłem, że Lock
i Condition
(i inne nowe concurrent
klasy) to po prostu więcej narzędzi do zestawu narzędzi. Mógłbym zrobić wszystko, czego potrzebowałem, za pomocą mojego starego młota pazurowego ( synchronized
słowo kluczowe), ale w niektórych sytuacjach korzystanie z niego było niewygodne. Kilka z tych niezręcznych sytuacji stało się o wiele prostszych, gdy dodałem więcej narzędzi do mojego zestawu narzędzi: gumowy młotek, młot kulkowy, prybar i kilka ciosów w gwoździe. Jednak mój stary młot pazur nadal widzi swój udział w użyciu.
Nie sądzę, aby jedno było naprawdę „lepsze” niż drugie, ale raczej każde lepiej pasuje do różnych problemów. W skrócie, prosty model i charakter zorientowany na zakres synchronized
pomaga chronić mnie przed błędami w moim kodzie, ale te same zalety są czasem przeszkodami w bardziej złożonych scenariuszach. To są te bardziej złożone scenariusze, że pakiet pomocniczy został stworzony, aby pomóc rozwiązać. Ale korzystanie z tego konstruktu wyższego poziomu wymaga bardziej wyraźnego i ostrożnego zarządzania kodem.
===
Myślę, że JavaDoc dobrze sobie radzi z opisywaniem rozróżnienia między Lock
i synchronized
(nacisk jest mój):
Implementacje blokady zapewniają szersze operacje blokowania, niż można uzyskać przy użyciu zsynchronizowanych metod i instrukcji. Pozwalają na bardziej elastyczną strukturę , mogą mieć zupełnie inne właściwości i mogą obsługiwać wiele powiązanych obiektów Warunków .
...
Zastosowanie zsynchronizowanych metod lub oświadczeń zapewnia dostęp do niejawnego blokady monitora związanego z każdego przedmiotu, ale siły wszystkim nabywanie i zwalniania blokady nastąpić w sposób blokowej strukturze : kiedy wielu zamki zostały nabyte one muszą zostać wydany w kolejności przeciwnej , a wszystkie blokady muszą być zwolnione w tym samym zakresie leksykalnym, w którym zostały nabyte .
Podczas gdy mechanizm określania zakresu dla zsynchronizowanych metod i instrukcji znacznie ułatwia programowanie przy użyciu blokad monitora i pomaga uniknąć wielu typowych błędów programowania związanych z blokadami, istnieją sytuacje, w których trzeba pracować z blokadami w bardziej elastyczny sposób. Na przykład * * niektóre algorytmy * do przechodzenia przez równolegle dostępne struktury danych wymagają użycia metody „hand-over-hand” lub „chain lock ” : nabywasz blokadę węzła A, następnie węzła B, a następnie zwalniasz A i nabywasz C, następnie zwolnij B i zdobądź D i tak dalej. Implementacje interfejsu Lock umożliwiają stosowanie takich technik, umożliwiając uzyskanie i zwolnienie blokady w różnych zakresach , orazumożliwiając uzyskanie i zwolnienie wielu zamków w dowolnej kolejności .
Ta zwiększona elastyczność wiąże się z dodatkową odpowiedzialnością . Nieobecność bloku o strukturze blokowania usuwa automatyczne zwolnienie blokad , które pojawiają się przy zsynchronizowanych metod i instrukcji. W większości przypadków należy zastosować następujący idiom:
...
Podczas blokowania i odblokowywania występują w różnych zakresach , należy zachować ostrożność, aby upewnić się, że cały kod, który jest wykonywany, kiedy blokada jest utrzymywana jest chroniony przez Try-końcu lub try-catch , aby upewnić się, że blokada zostanie zwolniona , gdy jest to konieczne.
Implementacje blokady zapewniają dodatkową funkcjonalność w stosunku do stosowania zsynchronizowanych metod i instrukcji, zapewniając nieblokującą próbę uzyskania blokady (tryLock ()), próbę uzyskania blokady, którą można przerwać (lockInterruptrupt (), oraz próbę uzyskania blokada, która może przekroczyć limit czasu (tryLock (long, TimeUnit)).
...