2013-08-27 5 views
5

Mam sytuację, w której wiele wątków będzie sondować pojedynczy numer BlockingQueue, dzwoniąc pod numer take(). Co chcę wiedzieć, to:BlockingQueues i kolejność dostępu do wątku

Jeśli wiele wątków czeka na kolejkę, aby odebrać element, będą miały pierwszeństwo do podejmowania elementów z kolejki w kolejności, w której wykonano ich wywołania() lub czy kolejność, w której wątki usuwają rzeczy z kolejki, będzie arbitralna?

Dzięki!

Uwaga: W przeszłości pisałem własne implementacje tego typu rzeczy, ale zastanawiam się, czy implementacje BlockingQueue w Javie zrobiłyby to za mnie.

+1

Zasadniczo każda aplikacja wielowątkowa nie powinna przyjmować żadnych założeń dotyczących kolejności wykonywania wątku. Istnieją sposoby na jego egzekwowanie, ale idea aplikacji MT polega na tym, że nie należy tego robić. – Dariusz

+1

Interesujące pytanie, napisałem i uruchomiłem program - nie ma ustalonego porządku. – Tala

+1

[Powiązane pytanie] (http://stackoverflow.com/questions/1301691/java-queue-implementations-which-one), które również omawia sprawiedliwość. –

Odpowiedz

4

To zależy od wdrożenia.

Jeśli używasz LinkedBlockingQueue Z take() metoda sprawdza się 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 

javadoc mówi

Konstruktor tej klasy akceptuje opcjonalny parametr sprawiedliwości. Po ustawieniu wartości true, pod rywalizacją, blokady decydują o przyznaniu dostępu do wątku o najdłuższym oczekiwaniu . W przeciwnym razie ta blokada nie gwarantuje żadnego szczególnego zamówienia dostępu. Programy wykorzystujące rzetelne blokady dostępne dla wielu wątków mogą wykazywać niższą ogólną przepustowość (tj. Są wolniejsze, często znacznie wolniej) niż te, które używają ustawienia domyślnego, ale mają mniejsze wariancje w czasie, aby uzyskać blokady i gwarantują brak wygłodzenia. Należy jednak pamiętać, że rzetelność zamków nie gwarantuje rzetelności harmonogramu wątków . Zatem jeden z wielu wątków używających rzetelnego zamka może uzyskać wiele razy jeden po drugim, podczas gdy inne aktywne wątki nie są w stanie przesuwać się, a obecnie nie blokują. Należy również pamiętać, że metoda untLock z nieuznanym kodem nie uwzględnia ustawienia uczciwości. Pomyślnie zakończy się , jeśli blokada jest dostępna, nawet jeśli oczekują inne wątki.

2

W wielu przypadkach javadocs wspominają, czy klasa jest "uczciwa", tj. Blokowanie jest rozprowadzane, aby wszystkie wątki miały tę samą szansę. To jednak nie musi oznaczać tego samego, co "dostaje w tej samej kolejności". Sprawdź javadocs pod kątem konkretnej implementacji kolejki, aby sprawdzić, czy zawiera informacje na temat uczciwości i/lub porządku.

Przynajmniej ArrayBlockingQueue informuje o uczciwości w następujący sposób:

Ta klasa obsługuje opcjonalną zasadę uczciwości do zamawiania czeka producentem a konsumentem wątki. Domyślnie to zamówienie nie jest gwarantowane na . Jednak kolejka skonstruowana z wartością prawdy ustawioną na wartość true zapewnia dostęp do wątków w kolejności FIFO. Sprawiedliwość ogólnie zmniejsza przepustowość , ale zmniejsza zmienność i zapobiega głodowi.

1

To zależy od implementacji, czy klasa obsługuje opcjonalną politykę uczciwości przy zamawianiu oczekujących wątków producenta i konsumenta, czy też nie. Na przykład.ArrayBlockingQueue może być uczciwy, ponieważ ma konstruktora ArrayBlockingQueue (pojemność int, fair boolean), ale cant LinkedBlockingQueue.

Powiązane problemy