J'ai 3 threads: 2 consommateurs, J'ai aussi une file d'attente LinkedBlockingQueue LinkedBlockingQuerQu. / code> p>
à T = 1: à T = 2: à t = 3: est-il garanti que le consommateur reçoit FOO avant la consommation? En d'autres termes, l'ordre dans lequel les consommateurs invoquent Si non, existe-t-il une structure de données alternative qui donnera une priorité supérieure basée sur la commande? P> Consumera code> et ConsumerB code> et un producteur p>. P>.
Consumera CODE> Appels File d'appels.take () P>
Consumer Code> B Appelle la file d'attente.take () P>
producteur code> appelle queue.put (foo) p>
prendre () code> est l'ordre dans lequel chacun est notifié? P>
3 Réponses :
de regarder le code source, il n'est pas garanti. Il y a un mécanisme de blocs gardé en place avec le réveil d'un fil au hasard, en fonction de la façon dont le planificateur se sent.
notEmpty.signal(); // propagate to a non-interrupted thread
Dans de nombreux cas, l'ordre des threads entrant dans la file d'attente sera dans l'ordre approprié. Cependant, la file d'attente LinkedBlocking utilise une serrure injuste. Ce que cela permet est de faire des fils de barger les uns sur les autres. Bien qu'il soit rare que ce qui suit pourrait arriver. P>
Ceci est une possibilité. P>
Ainsi de creuser dans les entrailles de la source Java 6 (sauter la pièce entre les règles horizontales si vous ne vous souciez pas de trouver le code réel responsable de cette substance) P>
java.util.concurrent.linkedblockingQueue code> implémente mutex en utilisant des instances de java.util.concurrent.lock.reentrantlock code>. p>
à son tour, les variables de synchronisation sont générées avec java.util.concurrent.lock.util.concurrent.lock.utilrantlock.newcondition () code> quels appels java.util.concurrent.lock.retrantlock $ synchronisation.newcondition ( ) code>. p>
la méthode java.util.concurrent.lock.reentrantlock $ sync.NewCondition () code> retourne une instance de java.util.concurrent.abracttiqueEUTENECUNISED $ ConditionObject code> qui implémente le Appels de variable de synchronisation normaux sur attendre () code>, signal () code> et signalAlall () code> décrit par l'interface java.util.concurrent. LOCKS.CONDIIITION CODE>. P>
En regardant le code source de la classe code> ConditionObject code>, il conserve deux membres appelés premier waiter code> et lastwaiter code> qui sont les premier et dernier nœuds de Une file d'attente de verrouillage CLH (instances de java.util.concurrent.locks.abstracttiqueEcueSynchronizer $ nœud code>). P>
La documentation dans cette classe étage: p>
Un thread peut essayer d'acquérir s'il est d'abord dans la file d'attente. Mais être d'abord ne garantit pas le succès; Cela ne donne que le droit de faire face. Donc, le thread de Contender actuellement publié peut-être besoin de redemander. Em> p>
Je crois donc que la réponse ici est que le prise () code> méthode dans linkedblockingQUEUEE code> tente de donner un traitement préférentiel à ces threads qui appelaient prendre () code> plus tôt. Il donnera au premier fil d'appeler prendre () code> la première chance de saisir une option de file d'attente lorsqu'il devient disponible, mais en raison des délais d'attente, des interruptions, etc. que le fil n'est pas garanti fort> être le premier fil pour obtenir l'article de la file d'attente. P>
Gardez à l'esprit que cela est complètement spécifique à cette mise en œuvre particulière. En général, vous devriez supposer que les appels vers prenez () code> réaliseront un fil d'attente aléatoire lorsqu'un élément de file d'attente devient disponible et pas nécessairement le premier appelé prise () code>. p>