Więc kopanie przez wnętrzności źródła Java 6 (pominąć udział między zasad horyzontalnych, jeśli nie dbają o znalezieniu rzeczywisty kod odpowiedzialny za te rzeczy)
Klasa
java.util.concurrent.LinkedBlockingQueue
realizuje używając mutex wystąpienia
java.util.concurrent.locks.ReentrantLock
.
Z kolei zmienne synchronizacyjne są generowane za pomocą java.util.concurrent.locks.ReentrantLock.newCondition()
, która wywołuje java.util.concurrent.locks.ReentrantLock$Sync.newCondition()
.
Sposób java.util.concurrent.locks.ReentrantLock$Sync.newCondition()
zwraca wystąpienie java.util.concurrent.AbstractQueuedSynchronizer$ConditionObject
który realizuje normalne połączenia zmiennej synchronizacji do await()
, signal()
i signalAll()
opisane przez interfejs java.util.concurrent.locks.Condiion
.
Patrząc na kod źródłowy dla klasy ConditionObject
, utrzymuje dwóch członków nazywa firstWaiter
i lastWaiter
, które są pierwsze i ostatnie węzły w kolejce blokady CLH (instancje java.util.concurrent.locks.AbstractQueuedSynchronizer$Node
).
Dokumentacja w tejże klasy:
Wątek mogą próbować pozyskać jeśli jest pierwszy w kolejce. Ale bycie pierwszym nie gwarantuje sukcesu; daje tylko prawo do walki. Tak więc obecnie opublikowany wątek rywalizacyjny może wymagać ponownego odczytania.
Więc uważam, że odpowiedź jest to, że metoda LinkedBlockingQueue
prób take()
dać preferencyjnego traktowania tych wątku nazwie take()
wcześniej. Da to pierwszy wątek, który wywoła take()
pierwszą szansę na chwycenie elementu kolejki, gdy stanie się dostępny, ale z powodu przekroczenia czasu, przerwań itp., Że wątek nie jest gwarantowany jako pierwszy wątek, aby uzyskać element poza kolejka.
Należy pamiętać, że jest to całkowicie specyficzne dla tej konkretnej implementacji. Generalnie powinieneś założyć, że wywołania do take()
obudzą losowy wątek oczekujący, gdy element kolejki stanie się dostępny i niekoniecznie pierwszy, który zadzwonił pod numer take()
.