Java Parallelität in der Praxis: Wettlaufbedingung in BoundedExecutor?

8

Es gibt etwas Seltsames an der Implementierung von BoundedExecutor im Buch Java Concurrency in Practice.

Es soll die Übergabe von Aufgaben an den Executor drosseln, indem der übergebende Thread blockiert wird, wenn genügend Threads entweder in der Warteschlange stehen oder im Executor ausgeführt werden.

Dies ist die Implementierung (nach dem Hinzufügen der fehlenden Wiederholung in der Fangklausel):

%Vor%

Wenn ich die BoundedExecutor mit einer Executors.newCachedThreadPool() und einer Grenze von 4 instanziiere, würde ich erwarten, dass die Anzahl der Threads, die durch den Cache-Thread-Pool instanziiert werden, niemals 4 überschreitet. In der Praxis jedoch tut es dies. Ich habe dieses kleine Testprogramm erstellt, um so viel wie 11 Threads zu erstellen:

%Vor%

Ich denke, es gibt einen winzigen kleinen Zeitrahmen zwischen der Freigabe des Semaphors und der Beendigung der Aufgabe, wo ein anderer Thread eine Genehmigung erwirbt und eine Aufgabe einreicht, während der Freigabethread noch nicht beendet ist. Mit anderen Worten, es hat eine Wettlaufbedingung.

Kann jemand das bestätigen?

    
Jan Van den bosch 10.04.2012, 18:04
quelle

3 Antworten

2

Ich sehe so viel wie 9 Threads auf einmal erstellt. Ich vermute, dass es eine Race-Bedingung gibt, die dazu führt, dass mehr Thread als erforderlich ist.

Dies könnte daran liegen, dass vor und nach dem Ausführen der Aufgabe Arbeit zu erledigen ist. Das bedeutet, dass, obwohl nur 4 Threads in Ihrem Code-Block vorhanden sind, eine Reihe von Threads eine vorherige Aufgabe beendet oder bereit ist, eine neue Aufgabe zu starten.

d. Der Thread macht eine Freigabe () während er noch läuft. Auch wenn es das letzte ist, was du tust, ist es nicht das letzte, was es macht, bevor du eine neue Aufgabe erlangst.

    
Peter Lawrey 10.04.2012, 18:22
quelle
10

BoundedExecutor war in der Tat als eine Veranschaulichung dafür gedacht, wie man die Aufgabeübertragung drosselt, und nicht als eine Möglichkeit, die Thread-Pool-Größe zu begrenzen. Es gibt direktere Wege, letzteres zu erreichen, wie zumindest ein Kommentar herausstellte.

Aber die anderen Antworten erwähnen nicht den Text in dem Buch, das eine unbegrenzte Warteschlange verwenden soll und

  

setzen Sie die Grenze für das Semaphor so, dass sie gleich der Poolgröße plus ist   Anzahl der eingereihten Aufgaben, die Sie zulassen möchten, da der Semaphor ist   die Anzahl der aktuell ausgeführten und wartenden Aufgaben begrenzen   Ausführung. [JCiP, Ende von Abschnitt 8.3.3]

Durch Erwähnung der unbegrenzten Warteschlangen und der Poolgröße implizieren wir (anscheinend nicht sehr deutlich) die Verwendung eines Thread-Pools begrenzter Größe.

Was mich bei BoundedExecutor jedoch immer gestört hat, ist, dass es die ExecutorService-Schnittstelle nicht implementiert. Eine moderne Methode, um ähnliche Funktionen zu erreichen und dennoch die Standardschnittstellen zu implementieren, wäre die Verwendung von Guavas ListeningDecorator -Methode und ForwardingListeningExecutorService Klasse.

    
Tim Peierls 11.04.2012 15:51
quelle
5

Sie haben in Ihrer Analyse der Wettlaufsituation Recht. Es gibt keine Synchronisationsgarantien zwischen dem ExecutorService & amp; der Semaphor.

Allerdings weiß ich nicht, ob der BoundedExecutor für die Anzahl der Threads gedrosselt wird. Ich denke, es ist mehr für die Drosselung der Anzahl der Aufgaben an den Dienst übermittelt. Stellen Sie sich vor, wenn Sie 5 Millionen Aufgaben haben, die Sie einreichen müssen, und wenn Sie mehr als 10.000 davon einreichen, haben Sie keinen Speicher mehr.

Nun, du wirst immer nur 4 Threads laufen haben, warum willst du alle 5 Millionen Aufgaben anstellen? Sie können ein ähnliches Konstrukt verwenden, um die Anzahl der Aufgaben zu begrenzen, die zu einem bestimmten Zeitpunkt in der Warteschlange stehen. Was Sie daraus machen sollten, ist, dass zu jedem Zeitpunkt nur 4 Aufgaben ausgeführt werden.

Offensichtlich ist die Lösung dafür, ein Executors.newFixedThreadPool(4) zu verwenden.

    
John Vint 10.04.2012 18:18
quelle