Czytałem przez interfejs API java.util.concurrent i znalazłem to
CountDownLatch
: Pomoc w synchronizacji, która pozwala jednemu lub większej liczbie wątków czekać na zakończenie zestawu operacji wykonywanych w innych wątkach.CyclicBarrier
: Pomoc w synchronizacji, która umożliwia zestawowi wątków czekanie na siebie nawzajem w celu osiągnięcia wspólnego punktu bariery.
Wydaje mi się, że oba wydają mi się równe, ale jestem pewien, że jest w tym znacznie więcej.
Na przykład w CoundownLatch, the countdown value could not be reset, that can happen in the case of CyclicBarrier
.
Czy jest między nimi jakaś inna różnica?
Jakie są miejsca, w use cases
których ktoś chciałby zresetować wartość odliczania?
java
concurrency
countdownlatch
cyclicbarrier
marzyciel
źródło
źródło
Odpowiedzi:
Jedną z głównych różnic jest to, że CyclicBarrier przyjmuje (opcjonalne) Runnable zadanie, które jest uruchamiane po spełnieniu wspólnego warunku bariery.
Pozwala również uzyskać liczbę klientów oczekujących przy szlabanie oraz liczbę wymaganą do uruchomienia bariery. Po uruchomieniu bariera jest resetowana i może być ponownie użyta.
W prostych przypadkach użycia - uruchamianie usług itp ... CountdownLatch jest w porządku. CyclicBarrier jest przydatny w przypadku bardziej złożonych zadań koordynacyjnych. Przykładem takiej rzeczy mogą być obliczenia równoległe - w których w obliczeniach zaangażowanych jest wiele podzadań - coś w rodzaju MapReduce .
źródło
Jest inna różnica.
Używając a
CyclicBarrier
, zakłada się, że określasz liczbę oczekujących wątków, które wyzwalają barierę. Jeśli określisz 5, musisz mieć co najmniej 5 wątków do wywołaniaawait()
.Używając a
CountDownLatch
, określasz liczbę wywołań,countDown()
które spowodują zwolnienie wszystkich oczekujących wątków. Oznacza to, że możesz użyćCountDownLatch
tylko z jednym wątkiem.Możesz powiedzieć: „Dlaczego miałbyś to zrobić?”. Wyobraź sobie, że używasz tajemniczego interfejsu API zakodowanego przez kogoś innego, który wykonuje wywołania zwrotne. Chcesz, aby jeden z Twoich wątków czekał, aż określone wywołanie zwrotne zostanie wywołane kilka razy. Nie masz pojęcia, w których wątkach zostanie wywołane wywołanie zwrotne. W tym przypadku a
CountDownLatch
jest idealne, podczas gdy nie mogę wymyślić żadnego sposobu zaimplementowania tego za pomocą aCyclicBarrier
(właściwie mogę, ale wymaga to przekroczenia limitu czasu ... fuj!).Chciałbym tylko, żeby
CountDownLatch
można było to zresetować!źródło
CountDownLatch
było je zresetować - obejściem, którego używam do implementacji zgrubnego powiadomienia o oczekiwaniu, jest po prostu ponowne uruchomienieCountDownLatch
natychmiast po wprowadzeniu chronionego bloku kodu (kiedy zatrzask osiągnie zero). Oczywiście nie ma to zastosowania we wszystkich okolicznościach / zakresach, ale pomyślałem, że warto zauważyć, że jest to opcja w sytuacjach złocistych.Java Concurrency in Practice
- mówi to samo:Latches are for waiting for events; barriers are for waiting for other threads.
. Podstawowy i niezbędny punkt do zrozumienia różnicy między tymi dwoma.Jedną kwestią, o której nikt jeszcze nie wspomniał, jest to, że
CyclicBarrier
jeśli wątek ma problem (przekroczenie limitu czasu, przerwanie ...), wszystkie inne, które osiągnęły,await()
otrzymują wyjątek. Zobacz Javadoc:źródło
Myślę, że JavaDoc wyraźnie wyjaśnił różnice. Większość ludzi wie, że CountDownLatch nie może zostać zresetowany, jednak CyclicBarrier tak. Ale to nie jedyna różnica, lub można zmienić nazwę CyclicBarrier na ResetbleCountDownLatch. Różnice powinniśmy rozróżnić z perspektywy ich celów, które są opisane w JavaDoc
CountDownLatch: pomoc w synchronizacji, która umożliwia co najmniej jednemu wątkowi oczekiwanie na zakończenie zestawu operacji wykonywanych w innych wątkach.
CyclicBarrier: pomoc w synchronizacji, która umożliwia zestawowi wątków czekanie na siebie nawzajem do osiągnięcia wspólnego punktu bariery.
W countDownLatch istnieje co najmniej jeden wątek, który czeka na zakończenie zestawu innych wątków . W tej sytuacji są dwa typy wątków, jeden typ czeka, inny coś robi, po zakończeniu zadań mogą czekać lub po prostu zostać zakończone.
W CyclicBarrier jest tylko jeden rodzaj wątków, czekają na siebie, są sobie równe.
źródło
Główna różnica jest udokumentowana bezpośrednio w Javadocs dla CountdownLatch. Mianowicie:
źródło 1.6 Javadoc
źródło
CountDownLatch służy do jednorazowej synchronizacji. Podczas korzystania z CountDownLatch każdy wątek może wywoływać funkcję countDown () dowolną liczbę razy. Wątki, które wywołały await (), są blokowane do zera z powodu wywołań funkcji countDown () przez inne niezablokowane wątki. Plik javadoc dla CountDownLatch stwierdza:
W przeciwieństwie do tego cykliczna bariera jest używana dla wielu punktów synchronizacji, np. Jeśli zestaw wątków wykonuje obliczenia pętlowe / fazowe i wymaga synchronizacji przed rozpoczęciem następnej iteracji / fazy. Zgodnie z javadoc dla CyclicBarrier :
W przeciwieństwie do CountDownLatch, każde wywołanie await () należy do jakiejś fazy i może powodować blokowanie wątku do momentu, gdy wszystkie strony należące do tej fazy wywołają await (). Nie ma jawnej operacji countDown () obsługiwanej przez parametr CyclicBarrier.
źródło
Na to pytanie udzielono już wystarczającej odpowiedzi, ale myślę, że mogę trochę dodać wartość, zamieszczając jakiś kod.
Aby zilustrować zachowanie cyklicznej bariery, stworzyłem przykładowy kod. Gdy tylko szlaban jest przechylony, jest on automatycznie resetowany, aby można go było ponownie użyć (stąd jest „cykliczny”). Po uruchomieniu programu zwróć uwagę, że wydruki „Zagrajmy” są wyzwalane dopiero po przechyleniu bariery.
źródło
Kiedy uczyłem się o zatrzaskach i cyklicznych barierach, wymyśliłem te metafory. cykliczne bariery : Wyobraź sobie, że firma ma salę konferencyjną. Aby rozpocząć spotkanie, pewna liczba uczestników spotkania musi przyjść na spotkanie (aby było ono oficjalne). poniżej znajduje się kod zwykłego uczestnika spotkania (pracownika)
pracownik dołącza do spotkania, czeka, aż inni przyjdą, aby rozpocząć spotkanie. też wychodzi, jeśli spotkanie zostanie odwołane :) wtedy mamy SZEFA, jak dawki nie lubią czekać, aż pojawią się inni, a jeśli straci pacjenta, odwołuje spotkanie.
W normalnym dniu pracownik przychodzi na spotkanie, czeka na pojawienie się innego, a jeśli niektórzy uczestnicy nie przychodzą, muszą czekać bez końca! na jakimś specjalnym spotkaniu szef przychodzi i nie lubi czekać. (5 osób musi zacząć spotkanie, ale przychodzi tylko szef i entuzjastyczny pracownik), więc odwołuje spotkanie (ze złością)
Wynik:
Istnieje inny scenariusz, w którym inny wątek z zewnątrz (trzęsienie ziemi) odwołuje spotkanie (metoda resetowania połączenia). w tym przypadku wszystkie oczekujące wątki zostaną obudzone przez wyjątek.
uruchomiony kod spowoduje zabawne wyjście:
Możesz także dodać sekretarkę do pokoju konferencyjnego, jeśli odbędzie się spotkanie, będzie dokumentować wszystko, ale nie jest częścią spotkania:
Zamki : jeśli wściekły szef chce zorganizować wystawę dla klientów firmy, wszystko musi być gotowe (zasoby). tworzymy listę rzeczy do zrobienia, każdy pracownik (Thread) dozuje swoją pracę i sprawdzamy listę rzeczy do zrobienia (jedni malują, inni przygotowują nagłośnienie ...). Kiedy wszystkie pozycje na liście zadań są kompletne (zasoby są dostępne), możemy otworzyć drzwi klientom.
A jak robotnicy przygotowują wystawę:
źródło
Krótko mówiąc , wystarczy zrozumieć kluczowe różnice funkcjonalne między nimi:
i
z wyjątkiem, oczywiście, funkcji takich jak nieblokowanie, czasowe oczekiwanie, diagnostyka i wszystko, co zostało szczegółowo wyjaśnione w powyższych odpowiedziach.
Powyższe klasy są jednak w pełni funkcjonalne i równoważne, w ramach dostarczonej funkcjonalności, swoim korespondentom.
Na innym uwaga,
CountDownLatch
„s wewnętrzne podklasy klasyAQS
, natomiastCyclicBarrier
zastosowaniaReentrantLock
(moje podejrzenie, że może być odwrotnie lub oba mogą korzystać zarówno AQS lub wykorzystanie lock - bez utraty wydajności wydajności)źródło
Jedną oczywistą różnicą jest to, że tylko N wątków może czekać na CyclicBarrier z N do uwolnienia w jednym cyklu. Ale nieograniczona liczba wątków może oczekiwać na CountDownLatch o wartości N. Odliczanie w dół można wykonać o jeden wątek N razy lub N wątków jeden raz lub kombinacje.
źródło
W przypadku CyclicBarrier, gdy tylko WSZYSTKIE wątki potomne zaczną wywoływać barrier.await (), Runnable jest wykonywany w Barrierze. Bariera. Czekanie w każdym dziecięcym wątku zajmie różną długość czasu, aby się skończyć i wszystkie kończą się w tym samym czasie.
źródło
W CountDownLatch główne wątki czekają na zakończenie wykonywania przez inne wątki. W CyclicBarrier wątki robocze czekają na siebie nawzajem na zakończenie wykonywania.
Nie możesz ponownie użyć tego samego CountDownLatch instancji gdy liczba osiągnie zero i zatrzask jest otwarty, z drugiej strony CyclicBarrier można ponownie wykorzystać, resetując barierę, gdy bariera zostanie złamana.
źródło
CountDownLatch to odliczanie wszystkiego; CyclicBarrier jest odliczaniem tylko dla wątku
Załóżmy, że jest 5 wątków roboczych i jeden wątek wysyłający, a gdy pracownicy wyprodukują 100 przedmiotów, nadawca je wyśle.
W przypadku CountDownLatch licznik może znajdować się na pracownikach lub przedmiotach
W przypadku CyclicBarrier licznik może działać tylko na robotnikach
Jeśli pracownik zasypia w nieskończoność, z CountDownLatch na przedmiotach, Shipper może wysłać; Jednak w przypadku CyclicBarrier nigdy nie można wywołać nadawcy
źródło
@Kevin Lee i @Jon Próbowałem CyclicBarrier z opcjonalnym Runnable. Wygląda na to, że działa na początku i po przechyleniu CyclicBarrier. Oto kod i dane wyjściowe
statyczna bariera CyclicBarrier;
Wynik
źródło