2013-08-27 3 views
5

Ich habe eine Situation, in der mehrere Threads einen einzelnen BlockingQueue durch Aufruf von take() abrufen werden. Folgendes möchte ich wissen:BlockingQueues und Thread-Zugriffsreihenfolge

Wenn mehrere Threads darauf warten, dass die Warteschlange ein Element empfängt, erhalten sie Vorrang, wenn sie Elemente aus der Warteschlange in der Reihenfolge abholen, in der sie ihre Aufrufe() oder ausgeführt haben Wird die Reihenfolge, in der die Threads Dinge aus der Warteschlange nehmen, willkürlich sein?

Danke!

Hinweis: Ich habe in der Vergangenheit meine eigenen Implementierungen für diese Art von Dingen geschrieben, aber ich frage mich, ob die BlockingQueue-Implementierungen in Java dies für mich tun würden.

+1

Im Allgemeinen sollte jede Multithread-Anwendung keine Annahmen über die Reihenfolge der Thread-Ausführung treffen. Es gibt Möglichkeiten, um es durchzusetzen, aber die Idee hinter MT-Anwendungen ist, dass es nicht getan werden sollte. – Dariusz

+1

Interessante Frage, ich habe geschrieben und lief ein Programm - es gibt keine feste Reihenfolge. – Tala

+1

[Verwandte Frage] (http://stackoverflow.com/questions/1301691/java-queue-implementations-which-one), die auch Fairness diskutiert. –

Antwort

4

Es hängt von der Implementierung ab.

Wenn Sie einen LinkedBlockingQueue verwenden, die take() Methode überprüft mit einem ReentrantLock

public E take() throws InterruptedException { 
    E x; 
    int c = -1; 
    final AtomicInteger count = this.count; 
    final ReentrantLock takeLock = this.takeLock; 
    takeLock.lockInterruptibly(); 
    ... 
} 

// declared as 
private final ReentrantLock takeLock = new ReentrantLock(); // no fairness argument, defaults to false 

Die javadoc sagt

Der Konstruktor für diese Klasse eine optionale Fairness-Parameter akzeptiert. Wenn diese Option aktiviert ist, werden Sperrungen bei Sperren bevorzugt, wenn der Zugriff auf den am längsten wartenden Thread gewährt wird. Andernfalls garantiert dieses Schloss keine bestimmte Zugriffsreihenfolge. Programme, die faire Sperren verwenden, auf die viele Threads zugreifen, können einen niedrigeren Gesamtdurchsatz anzeigen (d. H. Sind langsamer; oft viel langsamer) als diejenigen, die die Standardeinstellung verwenden, haben jedoch kleinere Abweichungen in Zeiten, um Sperren zu erhalten und Mangel an Hunger zu garantieren. Beachten Sie jedoch, dass Fairness von Schlössern keine Fairness von Thread-Planung garantiert. Somit kann einer von vielen Threads, die eine faire Sperre verwenden, mehrfach hintereinander erhalten, während andere aktive Threads nicht fortfahren und die Sperre derzeit nicht halten. Beachten Sie auch, dass die Methode untimed tryLock die Fairnesseinstellung nicht berücksichtigt. Es wird erfolgreich sein, wenn die Sperre verfügbar ist, auch wenn andere Threads warten.

2

In vielen Fällen erwähnen die Javadocs, ob die Klasse "fair" ist, d. H. Die Blockierung wird verteilt, so dass alle Threads die gleiche Chance erhalten. Dies bedeutet nicht unbedingt dasselbe wie "in der gleichen Reihenfolge". Überprüfen Sie die Javadocs für Ihre bestimmte Warteschlangenimplementierung, um festzustellen, ob sie Informationen zur Fairness und/oder Reihenfolge enthält.

Mindestens ArrayBlockingQueue informiert der Fairness wie folgt:

Diese Klasse unterstützt eine optionale Fairness Politik für die Bestellung Erzeuger- und Verbraucher Threads warten. Standardmäßig ist diese Bestellung nicht garantiert. Eine Warteschlange, die mit Fairness auf True erstellt wurde, gewährt Thread-Zugriff in FIFO-Reihenfolge. Fairness verringert im Allgemeinen Durchsatz, reduziert aber die Variabilität und vermeidet Hunger.

1

Es hängt von der Implementierung ab, ob eine Klasse eine optionale Fairness-Richtlinie für die Bestellung wartender Erzeuger- und Verbraucher-Threads unterstützt oder nicht. Z.B.ArrayBlockingQueue kann fair sein, da es den Konstruktor ArrayBlockingQueue (int capacity, boolean fair), aber LinkedBlockingQueue cant hat.

Verwandte Themen