8
votes

Java: Est-ce que LinkedBlockingQueue prend en compte l'ordre des consommateurs?

J'ai 3 threads: 2 consommateurs, Consumera et ConsumerB et un producteur . .

J'ai aussi une file d'attente LinkedBlockingQueue LinkedBlockingQuerQu. / code>

à T = 1: Consumera Appels File d'appels.take ()

à T = 2: Consumer B Appelle la file d'attente.take ()

à t = 3: producteur appelle queue.put (foo)

est-il garanti que le consommateur reçoit FOO avant la consommation? En d'autres termes, l'ordre dans lequel les consommateurs invoquent prendre () est l'ordre dans lequel chacun est notifié?

Si non, existe-t-il une structure de données alternative qui donnera une priorité supérieure basée sur la commande?


0 commentaires

3 Réponses :


4
votes

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


0 commentaires

4
votes

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.

  • thread a entre et sondages.
  • thread b entre Essayé de sonder - fileter A contient le fil de verrouillage et de parcs b.
  • fil une finition et des signaux B
  • thread c entre et acquiert la serrure avant que B dans tout ce qui est complètement
  • Le fil b essaie de sonder - thread c maintient le fil de serrure et des parcs b.

    Ceci est une possibilité.


0 commentaires

2
votes

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)


La classe java.util.concurrent.linkedblockingQueue implémente mutex en utilisant des instances de java.util.concurrent.lock.reentrantlock .

à son tour, les variables de synchronisation sont générées avec java.util.concurrent.lock.util.concurrent.lock.utilrantlock.newcondition () quels appels java.util.concurrent.lock.retrantlock $ synchronisation.newcondition ( ) .

la méthode java.util.concurrent.lock.reentrantlock $ sync.NewCondition () retourne une instance de java.util.concurrent.abracttiqueEUTENECUNISED $ ConditionObject qui implémente le Appels de variable de synchronisation normaux sur attendre () , signal () et signalAlall () décrit par l'interface java.util.concurrent. LOCKS.CONDIIITION .


En regardant le code source de la classe ConditionObject , il conserve deux membres appelés premier waiter et lastwaiter 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 ).

La documentation dans cette classe étage:

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.

Je crois donc que la réponse ici est que le prise () méthode dans linkedblockingQUEUEE tente de donner un traitement préférentiel à ces threads qui appelaient prendre () plus tôt. Il donnera au premier fil d'appeler prendre () 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 être le premier fil pour obtenir l'article de la file d'attente.

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 () 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 () .


0 commentaires