Czy jest jakaś korzyść z używania
java.util.concurrent.CountdownLatch
zamiast
java.util.concurrent.Semaphore ?
O ile wiem, poniższe fragmenty są prawie równoważne:
1. Semafor
final Semaphore sem = new Semaphore(0);
for (int i = 0; i < num_threads; ++ i)
{
Thread t = new Thread() {
public void run()
{
try
{
doStuff();
}
finally
{
sem.release();
}
}
};
t.start();
}
sem.acquire(num_threads);
2: CountDownLatch
final CountDownLatch latch = new CountDownLatch(num_threads);
for (int i = 0; i < num_threads; ++ i)
{
Thread t = new Thread() {
public void run()
{
try
{
doStuff();
}
finally
{
latch.countDown();
}
}
};
t.start();
}
latch.await();
Tyle że w przypadku # 2 zatrzasku nie można ponownie użyć i co ważniejsze, musisz wcześniej wiedzieć, ile wątków zostanie utworzonych (lub poczekaj, aż wszystkie zostaną uruchomione, zanim utworzysz zatrzask).
Więc w jakiej sytuacji może być preferowany zatrzask?
CountDownLatch służy do uruchamiania serii wątków, a następnie czekania, aż wszystkie z nich zostaną ukończone (lub do wywołania
countDown()
określonej liczby razy.Semafor służy do kontrolowania liczby współbieżnych wątków używających zasobu. Ten zasób może być czymś w rodzaju pliku lub procesorem, ograniczając liczbę wykonywanych wątków. Licznik semafora może rosnąć i maleć, gdy różne wątki wywołują
acquire()
irelease()
.W twoim przykładzie zasadniczo używasz Semaphore jako rodzaju Count UP Latch. Biorąc pod uwagę, że Twoim zamiarem jest zaczekanie na zakończenie wszystkich wątków, użycie funkcji
CountdownLatch
sprawia, że Twój zamiar jest jaśniejszy.źródło
Krótkie podsumowanie:
Semaphore
iCountDownLatch
służy różnym celom.Służy
Semaphore
do kontrolowania dostępu wątków do zasobu.Służy
CountDownLatch
do czekania na zakończenie wszystkich wątkówSemaphore
definicja z Javadocs:Jednak żadne rzeczywiste obiekty zezwoleń nie są używane; po
Semaphore
prostu liczy dostępną liczbę i działa odpowiednio.Jak to działa?
Semafory są używane do kontrolowania liczby współbieżnych wątków, które używają zasobu. Może to być coś w rodzaju udostępnionych danych, blok kodu ( sekcja krytyczna ) lub dowolny plik.
Liczba na a
Semaphore
może rosnąć i maleć, gdy różne wątki wywołująacquire()
irelease()
. Ale w dowolnym momencie nie możesz mieć większej liczby wątków niż liczba semaforów.Semaphore
Przypadków użycia:Zapoznaj się z tym artykułem dotyczącym zastosowań semaforów.
CountDownLatch
definicja z Javadocs:Jak to działa?
CountDownLatch
działa poprzez zainicjowanie licznika liczbą wątków, która jest zmniejszana za każdym razem, gdy wątek kończy wykonywanie. Gdy liczba osiągnie zero, oznacza to, że wszystkie wątki zakończyły wykonywanie, a wątek oczekujący na zatrzask wznawia wykonywanie.CountDownLatch
Przypadków użycia:Zapoznaj się z tym artykułem, aby dobrze zrozumieć
CountDownLatch
pojęcia.Zajrzyj też do Fork Join Pool w tym artykule . Ma pewne podobieństwa do
CountDownLatch
.źródło
Powiedzmy, że wszedłeś do profesjonalnego sklepu golfowego z nadzieją, że znajdziesz czwórkę,
Kiedy stoisz w kolejce, aby uzyskać czas na tee od jednego z pracowników sklepu pro, w zasadzie dzwoniłeś
proshopVendorSemaphore.acquire()
, a kiedy już miałeś czas na tee,proshopVendorSemaphore.release()
dzwoniłeś . Uwaga: każdy z bezpłatnych opiekunów może ci pomóc, tj. Udostępnić zasoby.Teraz podchodzisz do startera, on uruchamia
CountDownLatch(4)
i dzwoni,await()
aby poczekać na innych, ze swojej strony zadzwoniłeś do check-in tjCountDownLatch
.countDown()
podobnie jak reszta czwórki. Kiedy wszyscy przybędą, starter daje śmiało (await()
zwrot połączenia)Teraz, po dziewięciu dołkach, kiedy każdy z was robi sobie przerwę, hipotetycznie włączamy ponownie startera, on używa „nowego”
CountDownLatch(4)
do wybicia otworu 10, to samo czekanie / synchronizacja jak otwór 1.Jeśli jednak starter użył a
CyclicBarrier
na początku, mógłby zresetować tę samą instancję w otworze 10 zamiast drugiego zatrzasku, który używa & rzuć.źródło
Patrząc na ogólnodostępne źródło, nie ma magii w implementacji tych dwóch klas, więc ich wydajność powinna być bardzo podobna. Wybierz ten, który sprawia, że Twój zamiar jest bardziej oczywisty.
źródło
CountdownLatch
powoduje, że wątki czekają naawait()
metodę, aż licznik osiągnie zero. Więc może chcesz, aby wszystkie twoje wątki czekały do 3 wywołań czegoś, a następnie wszystkie wątki mogą zostać przeniesione.Latch
Generalnie nie może być skasowany.A
Semaphore
pozwala wątkom na pobieranie zezwoleń, co zapobiega jednoczesnemu wykonywaniu zbyt wielu wątków, blokując, jeśli nie może uzyskać zezwoleń wymaganych do kontynuowania. Zezwolenia mogą zostać zwrócone do, abySemaphore
umożliwić kontynuowanie innych oczekujących wątków.źródło