Je lisais l' API java.util.concurrent et j'ai trouvé que
CountDownLatch
: Une aide à la synchronisation qui permet à un ou plusieurs threads d'attendre la fin d'un ensemble d'opérations en cours d'exécution dans d'autres threads.CyclicBarrier
: Une aide à la synchronisation qui permet à un ensemble de threads d'attendre tous les uns les autres pour atteindre un point de barrière commun.
Pour moi, les deux me semblent égaux, mais je suis sûr qu'il y a beaucoup plus.
Par exemple, dans CoundownLatch, the countdown value could not be reset, that can happen in the case of CyclicBarrier
.
Y a-t-il une autre différence entre les deux?
Quels sont les use cases
endroits où quelqu'un voudrait réinitialiser la valeur du compte à rebours?
Réponses:
Une différence majeure est que CyclicBarrier prend une tâche (facultative) qui est exécutée une fois que la condition de barrière commune est remplie.
Il vous permet également d'obtenir le nombre de clients en attente à la barrière et le nombre requis pour déclencher la barrière. Une fois déclenchée, la barrière est réinitialisée et peut être réutilisée.
Pour les cas d'utilisation simples - services démarrant, etc., un CountdownLatch convient. Un CyclicBarrier est utile pour des tâches de coordination plus complexes. Un exemple d'une telle chose serait le calcul parallèle - où plusieurs sous-tâches sont impliquées dans le calcul - un peu comme MapReduce .
la source
Il y a une autre différence.
Lorsque vous utilisez a
CyclicBarrier
, l'hypothèse est que vous spécifiez le nombre de threads en attente qui déclenchent la barrière. Si vous spécifiez 5, vous devez avoir au moins 5 threads à appelerawait()
.Lorsque vous utilisez a
CountDownLatch
, vous spécifiez le nombre d'appels verscountDown()
qui entraîneront la libération de tous les threads en attente. Cela signifie que vous pouvez utiliser unCountDownLatch
avec un seul thread."Pourquoi feriez-vous cela?", Pourriez-vous dire. Imaginez que vous utilisez une mystérieuse API codée par quelqu'un d'autre qui effectue des rappels. Vous voulez que l'un de vos threads attende qu'un certain rappel ait été appelé plusieurs fois. Vous ne savez pas sur quels threads le rappel sera appelé. Dans ce cas, a
CountDownLatch
est parfait, alors que je ne vois aucun moyen d'implémenter cela en utilisant unCyclicBarrier
(en fait, je peux, mais cela implique des délais d'attente ... beurk!).Je souhaite juste que cela
CountDownLatch
puisse être réinitialisé!la source
CountDownLatch
d'être réinitialisable - une solution de contournement que j'utilise pour implémenter une notification d'attente approximative consiste simplement à recommencerCountDownLatch
immédiatement lorsque le bloc de code protégé est entré (lorsque le verrou atteint zéro). Ce n'est pas applicable dans toutes les circonstances / portées bien sûr, mais j'ai pensé qu'il vaut la peine de noter que c'est une option dans les situations de boucles d'or.Java Concurrency in Practice
- dit la même chose:Latches are for waiting for events; barriers are for waiting for other threads.
. Un point primordial et essentiel pour comprendre la différence entre ces deux.Un point que personne n'a encore évoqué est que, dans un
CyclicBarrier
, si un thread a un problème (timeout, interrompu ...), tous les autres qui ont atteintawait()
obtiennent une exception. Voir Javadoc:la source
Je pense que le JavaDoc a expliqué les différences explicitement. La plupart des gens savent que CountDownLatch ne peut pas être réinitialisé, mais CyclicBarrier le peut. Mais ce n'est pas la seule différence, ou CyclicBarrier pourrait être renommé ResetbleCountDownLatch. Nous devons distinguer les différences du point de vue de leurs objectifs, qui sont décrits dans JavaDoc
CountDownLatch: aide à la synchronisation qui permet à un ou plusieurs threads d'attendre la fin d'un ensemble d'opérations en cours d'exécution dans d'autres threads.
CyclicBarrier: Une aide à la synchronisation qui permet à un ensemble de threads d'attendre tous les uns les autres pour atteindre un point de barrière commun.
Dans countDownLatch, il existe un ou plusieurs threads qui attendent la fin d'un ensemble d' autres threads . Dans cette situation, il existe deux types de threads, un type est en attente, un autre type fait quelque chose, après avoir terminé leurs tâches, ils peuvent être en attente ou simplement terminés.
Dans CyclicBarrier, il n'y a qu'un seul type de threads, ils s'attendent les uns les autres, ils sont égaux.
la source
La principale différence est documentée directement dans les Javadocs pour CountdownLatch. À savoir:
source 1.6 Javadoc
la source
Un CountDownLatch est utilisé pour une synchronisation ponctuelle. Lors de l'utilisation d'un CountDownLatch, tout thread est autorisé à appeler countDown () autant de fois qu'il le souhaite. Les threads qui ont appelé wait () sont bloqués jusqu'à ce que le nombre atteigne zéro en raison des appels à countDown () par d'autres threads non bloqués. Le javadoc pour CountDownLatch indique:
En revanche, la barrière cyclique est utilisée pour plusieurs points de synchronisation, par exemple si un ensemble de threads exécute un calcul en boucle / en phase et doit se synchroniser avant de commencer l'itération / phase suivante. Selon le javadoc pour CyclicBarrier :
Contrairement à CountDownLatch, chaque appel à await () appartient à une phase et peut provoquer le blocage du thread jusqu'à ce que toutes les parties appartenant à cette phase aient appelé wait (). Il n'y a pas d'opération countDown () explicite prise en charge par CyclicBarrier.
la source
Cette question a déjà reçu une réponse adéquate, mais je pense que je peux ajouter un peu de valeur en publiant du code.
Pour illustrer le comportement de la barrière cyclique, j'ai créé un exemple de code. Dès que la barrière est basculée, elle est automatiquement réinitialisée pour pouvoir être réutilisée (elle est donc "cyclique"). Lorsque vous exécutez le programme, observez que les impressions "Jouons" ne sont déclenchées qu'après le basculement de la barrière.
la source
Lorsque j'étudiais sur les verrous et les barrières cycliques, j'ai trouvé ces métaphores. cyclicbarriers : Imaginez qu'une entreprise dispose d'une salle de réunion. Pour démarrer la réunion, un certain nombre de participants doivent venir à la réunion (pour la rendre officielle). ce qui suit est le code d'un participant normal à une réunion (un employé)
l'employé se joint à la réunion, attend que d'autres viennent pour commencer la réunion. aussi il est sorti si la réunion est annulée :) alors nous avons THE BOSS comment les doses n'aiment pas attendre que les autres se présentent et s'il perd son patient, il annule la réunion.
Un jour normal, les employés viennent à la réunion en attendant que d'autres se présentent et si certains participants ne viennent pas, ils doivent attendre indéfiniment! dans une réunion spéciale, le patron vient et il n'aime pas attendre. (5 personnes doivent commencer à se rencontrer mais seul le patron vient et aussi un employé enthousiaste) alors il annule la réunion (avec colère)
Production:
Il existe un autre scénario dans lequel un autre thread extérieur (un tremblement de terre) annule la réunion (méthode de réinitialisation des appels). dans ce cas, tous les threads en attente sont réveillés par une exception.
l'exécution de code entraînera une sortie amusante:
Vous pouvez également ajouter une secrétaire à la salle de réunion, si une réunion a lieu, elle documentera tout mais elle ne fait pas partie de la réunion:
Loquets : si le patron en colère veut organiser une exposition pour les clients de l'entreprise, tout doit être prêt (ressources). nous fournissons une liste de tâches à chaque travailleur (Thread) dose son travail et nous vérifions la liste de tâches (certains travailleurs font de la peinture, d'autres préparent un système de sonorisation ...). lorsque tous les éléments de la liste de tâches sont terminés (les ressources sont fournies), nous pouvons ouvrir les portes aux clients.
Et les ouvriers comment préparent l'exposition:
la source
En un mot , juste pour comprendre les principales différences fonctionnelles entre les deux:
et
sauf, bien sûr, des fonctionnalités telles que le non-blocage, l'attente chronométrée, les diagnostics et tout ce qui a été expliqué en détail dans les réponses ci-dessus.
Les classes ci-dessus sont, cependant, entièrement fonctionnelles et équivalentes, dans les fonctionnalités fournies, à leurs homonymes correspondants.
Sur une note différente,
CountDownLatch
les sous-classes de la classe interne deAQS
, whileCyclicBarrier
usesReentrantLock
(je soupçonne que cela pourrait être l'inverse ou les deux pourraient utiliser AQS ou les deux utiliser Lock - sans aucune perte d'efficacité des performances)la source
Une différence évidente est que seuls N threads peuvent attendre sur un CyclicBarrier de N pour être libérés en un cycle. Mais un nombre illimité de threads peut attendre sur un CountDownLatch de N. La décrémentation du compte à rebours peut être effectuée par un thread N fois ou N threads une fois chacun ou des combinaisons.
la source
Dans le cas de CyclicBarrier, dès que TOUS les threads enfants commencent à appeler barrière.await (), le Runnable est exécuté dans la barrière. La barrière qui attend dans chaque thread enfant prendra un temps différent pour se terminer, et ils finissent tous en même temps.
la source
Dans CountDownLatch , les threads principaux attendent que les autres threads terminent leur exécution. Dans CyclicBarrier , les threads de travail attendent les uns les autres pour terminer leur exécution.
Vous ne pouvez pas réutiliser la même instance de CountDownLatch une fois que le nombre atteint zéro et que le verrou est ouvert, par contre, CyclicBarrier peut être réutilisé en réinitialisant Barrier, Une fois que la barrière est cassée.
la source
CountDownLatch est un compte à rebours de tout; CyclicBarrier est un compte à rebours pour thread uniquement
Supposons qu'il y ait 5 fils de travail et un fil d'expéditeur, et lorsque les travailleurs produisent 100 articles, l'expéditeur les expédiera.
Pour CountDownLatch, le compteur peut être sur des travailleurs ou des éléments
Pour CyclicBarrier, le compteur ne peut que sur les travailleurs
Si un ouvrier dort infiniment, avec CountDownLatch sur les articles, l'expéditeur peut expédier; Cependant, avec CyclicBarrier, Shipper ne peut jamais être appelé
la source
@Kevin Lee et @Jon J'ai essayé CyclicBarrier avec Optional Runnable. On dirait qu'il s'exécute au début et après le basculement de CyclicBarrier. Voici le code et la sortie
barrière statique CyclicBarrier;
Production
la source