Gibt es einen Vorteil der Verwendung
java.util.concurrent.CountdownLatch
anstatt
java.util.concurrent.Semaphore ?
Soweit ich das beurteilen kann, sind die folgenden Fragmente fast gleichwertig:
1. Semaphor
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();
Abgesehen davon, dass in Fall 2 der Latch nicht wiederverwendet werden kann und vor allem müssen Sie im Voraus wissen, wie viele Threads erstellt werden (oder warten Sie, bis alle gestartet sind, bevor Sie den Latch erstellen).
In welcher Situation könnte der Riegel also vorzuziehen sein?
CountDownLatch wird verwendet, um eine Reihe von Threads zu starten und dann zu warten, bis alle abgeschlossen sind (oder bis sie
countDown()
eine bestimmte Anzahl von Malen aufrufen .Semaphor wird verwendet, um die Anzahl der gleichzeitigen Threads zu steuern, die eine Ressource verwenden. Diese Ressource kann so etwas wie eine Datei sein oder die CPU, indem die Anzahl der ausgeführten Threads begrenzt wird. Die Anzahl auf einem Semaphor kann auf und ab gehen, wenn verschiedene Threads
acquire()
und aufrufenrelease()
.In Ihrem Beispiel verwenden Sie Semaphore im Wesentlichen als eine Art Count- Up- Latch. Da Sie beabsichtigen, auf die Fertigstellung aller Threads zu warten,
CountdownLatch
wird Ihre Absicht durch die Verwendung von klarer.quelle
Kurze Zusammenfassung:
Semaphore und CountDownLatch dienen unterschiedlichen Zwecken.
Verwenden Sie Semaphore , um den Thread-Zugriff auf Ressourcen zu steuern.
Verwenden Sie CountDownLatch , um auf den Abschluss aller Threads zu warten
Semaphordefinition aus Javadocs:
Es werden jedoch keine tatsächlichen Genehmigungsobjekte verwendet. Das Semaphor zählt nur die verfügbare Anzahl und handelt entsprechend.
Wie funktioniert es ?
Semaphoren werden verwendet, um die Anzahl der gleichzeitigen Threads zu steuern, die eine Ressource verwenden. Diese Ressource kann so etwas wie freigegebene Daten oder ein Codeblock ( kritischer Abschnitt ) oder eine beliebige Datei sein.
Die Anzahl auf einem Semaphor kann steigen und fallen, wenn verschiedene Threads
acquire
() undrelease
() aufrufen . Zu jedem Zeitpunkt können Sie jedoch nicht mehr Threads als die Anzahl der Semaphore haben.Anwendungsfälle für Semaphore:
Schauen Sie sich diesen Artikel für Semaphor-Anwendungen an.
CountDownLatch- Definition aus Javadocs:
Wie funktioniert es?
CountDownLatch funktioniert, indem ein Zähler mit der Anzahl der Threads initialisiert wird, der jedes Mal dekrementiert wird, wenn ein Thread seine Ausführung abschließt. Wenn die Anzahl Null erreicht, bedeutet dies, dass alle Threads ihre Ausführung abgeschlossen haben und der auf den Latch wartende Thread die Ausführung fortsetzt.
CountDownLatch Anwendungsfälle:
Schauen Sie sich diesen Artikel an, um die CountDownLatch-Konzepte klar zu verstehen.
Schauen Sie sich auch Fork Join Pool in diesem Artikel an . Es hat einige Ähnlichkeiten mit CountDownLatch .
quelle
Angenommen, Sie sind in den Golf Pro Shop gegangen und haben gehofft, einen Vierer zu finden.
Wenn Sie in der Schlange stehen, um eine Startzeit von einem der Pro-Shop-
proshopVendorSemaphore.acquire()
Mitarbeiter zu erhalten, haben Sie im Wesentlichen angerufen . Sobald Sie eineproshopVendorSemaphore.release()
Startzeit erhalten haben , haben Sie angerufen. Hinweis: Jeder der kostenlosen Mitarbeiter kann Sie bedienen, dh eine gemeinsam genutzte Ressource.Jetzt gehst du zum Starter, er startet ein
CountDownLatch(4)
und ruftawait()
an, um auf andere zu warten, für deinen Teil hast du eingecheckt, dhCountDownLatch
.countDown()
und der Rest der Vierer auch. Wenn alle ankommen, gibt der Starter los (await()
Anruf kehrt zurück)Jetzt, nach neun Löchern, in denen jeder von Ihnen eine Pause einlegt, lässt er hypothetisch wieder den Starter einbeziehen. Er verwendet ein 'neues'
CountDownLatch(4)
, um Loch 10 abzuschlagen, das gleiche Warten / Synchronisieren wie Loch 1.Wenn der Starter jedoch zunächst a verwendet
CyclicBarrier
hätte, hätte er dieselbe Instanz in Loch 10 anstelle eines zweiten Latch zurücksetzen können, der & throw verwendet.quelle
Wenn man sich die frei verfügbare Quelle ansieht, ist die Implementierung der beiden Klassen nicht magisch, daher sollte ihre Leistung weitgehend gleich sein. Wählen Sie diejenige, die Ihre Absicht offensichtlicher macht.
quelle
CountdownLatch
Lässt Threads auf dieawait()
Methode warten , bis die Anzahl Null erreicht hat. Vielleicht möchten Sie, dass alle Ihre Threads bis zu 3 Aufrufen von etwas warten, dann können alle Threads gehen. ALatch
kann generell nicht zurückgesetzt werden.A
Semaphore
ermöglicht es Threads, Genehmigungen abzurufen, wodurch verhindert wird, dass zu viele Threads gleichzeitig ausgeführt werden, und blockiert, wenn die zum Fortfahren erforderlichen Genehmigungen nicht abgerufen werden können. Berechtigungen können an a zurückgegeben werden,Semaphore
damit die anderen wartenden Threads fortfahren können.quelle