Un exemple est donné par l'un de nos entraîneurs lorsqu'il expliquait la différence entre CountDownLatch et CyclicBarrier.
CountDownLatch
: Supposons qu'une pierre puisse être levée par 10 personnes, vous devrez donc attendre que les 10 personnes viennent. Alors seulement vous pourrez soulever la pierre.
CyclicBarrier
: Si vous allez à un pique-nique et que vous devez d'abord vous rencontrer à un point commun à partir duquel vous commencerez tous votre voyage.
Si quelqu'un est d'accord avec ces commentaires, donnez-moi quelques détails.
J'ai déjà lu l'API Sun pour ces deux classes. Mais j'ai besoin de plus d'explications.
La principale différence est que CountDownLatch
sépare les threads en serveurs et arriver tandis que tous les threads utilisant un CyclicBarrier
remplissent les deux rôles.
Votre exemple de verrouillage implique que les dix personnes doivent attendre pour soulever la pierre ensemble. Ce n'est pas le cas. Un meilleur exemple du monde réel serait un animateur d’examen qui attend patiemment que chaque élève présente son test. Les étudiants n'attendent pas une fois qu'ils ont terminé leurs examens et sont libres de partir. Une fois que le dernier étudiant a passé l'examen (ou que le délai imparti expire), le prompteur cesse d'attendre et quitte les tests.
Dans un théâtre hypothétique,
ça s'appelle Mutex si une seule personne permet de regarder le jeu
Il est appelé Sémaphore si N nombre de personnes permettent de regarder la pièce. Si quelqu'un quitte le Théâtre pendant la pièce, il est alors permis à une autre personne de la regarder.
On l’appelle CountDownLatch si personne n’est autorisé à entrer jusqu’à ce que chaque personne quitte le théâtre. Chaque personne a le libre choix de quitter le théâtre.
Il s’appelle Cyclicbarrier si le théâtre ne commence pas tant que tout le monde n’y entre pas. Ici, l'homme de spectacle ne peut pas commencer le spectacle avant que toute la personne entre et attrape le siège. Une fois la pièce terminée, la même barrière s'appliquera pour le prochain spectacle.
Ici, la personne est un fil, le jeu est une ressource.
Exemple du monde réel Je peux voir que toutes les réponses manquent en réalité d'un exemple réel. Comme dans la façon dont ces classes peuvent être utilisées dans un domaine logiciel
CountDownLatch Un gestionnaire de téléchargement multithreaded. Le gestionnaire de téléchargement lancera plusieurs threads pour télécharger chaque partie du fichier simultanément (à condition que le serveur prenne en charge plusieurs threads à télécharger). Ici, chaque thread appellera une méthode de compte à rebours d'un verrou instancié. Une fois que tous les threads ont été exécutés, le thread associé au verrou de compte à rebours intégrera les pièces trouvées dans les différentes pièces dans un seul fichier.
CyclicBarrier Même scénario que ci-dessus..Mais supposons que les fichiers sont téléchargés à partir de P2P. Encore une fois plusieurs fils téléchargeant les morceaux. Mais dans ce cas, supposons que vous souhaitiez que la vérification de l’intégrité pour les morceaux téléchargés soit effectuée après un intervalle de temps particulier. La barrière cyclique joue ici un rôle important. Après chaque intervalle de temps, chaque thread attendra à la barrière pour que le thread associé à cyclibarrier puisse effectuer le contrôle d'intégrité. Ce contrôle d'intégrité peut être effectué plusieurs fois grâce à CyclicBarrier
S'il vous plaît corrigez-moi si quelque chose ne va pas.
Cas d'utilisation 1 / Supposons que vous ayez divisé un travail volumineux en 10 petites tâches, chacune sous la forme d'un fil. Vous devez attendre la fin des 10 tâches de ces threads avant de considérer le travail effectué.
Ainsi, le thread initiateur du travail principal initialise CountDownLatch au nombre de threads utilisés, il répartit les tâches entre les threads et attend que le verrou lève zéro avec la méthode await
. Chaque thread exécuteur invoquera countDown
à la fin de sa tâche. Enfin, le thread principal sera réveillé lorsque tous les threads seront terminés, de sorte qu'il considère que tout le travail est terminé. Ce scénario utilise le verrou doneSignal
décrit dans le javadoc CountDownLatch.
Cas d'utilisation 2 / Supposons que vous ayez divisé un travail volumineux en n * m tâches, réparties sur n threads. m correspond à une ligne de la matrice et vous avez un total à calculer pour chaque ligne. Dans ce cas, les threads doivent être synchronisés à la fin de chaque tâche pour que le total de la ligne soit calculé. Dans ce cas, une CyclicBarrier
initialisée avec le nombre de threads n est utilisée pour attendre la fin du calcul de chaque ligne (m fois en fait).
Pour comparer les deux, la CountDownLatch
est supposée être utilisée une seule fois et une CyclicBarrier
peut être utilisée autant de fois que l'algorithme nécessite un point de synchronisation pour un ensemble de threads.
Une CyclicBarrier
est réutilisable. Il s’agit donc plutôt d’une course où tout le monde se retrouve à un point de cheminement avant de passer à la prochaine étape de la tournée.
Différence théorique:
Dans CountDownLatch, les threads principaux attendent que les autres threads terminent leur exécution. Dans CyclicBarrier, les threads de travail s’attendent mutuellement pour terminer leur exécution.
Vous ne pouvez pas réutiliser la même instance CountDownLatch une fois que le nombre est atteint et que le verrouillage est ouvert. CyclicBarrier peut être réutilisé en réinitialisant Barrier, une fois la barrière brisée.
Exemple de la vie réelle: -
CountDownLatch: Prenons un scénario de monde informatique dans lequel le responsable se divise en modules entre les équipes de développement (A et B) et souhaite l'assigner à l'équipe d'assurance qualité pour qu'elle ne soit testée que lorsque les deux équipes ont terminé.
Ici, le fil de gestion fonctionne comme fil principal et l'équipe de développement en tant que fil de travail. Le thread du gestionnaire attend que le thread des équipes de développement termine sa tâche.
CyclicBarrier: Prenons le même scénario de monde informatique dans lequel le gestionnaire a divisé les modules entre les équipes de développement (A et B). Il part en congé et demande aux deux équipes d'attendre l'une l'autre de terminer leur tâche respective une fois que toutes les deux terminées, de l'attribuer à l'équipe d'assurance qualité pour la tester.
Ici, le fil de gestion fonctionne comme fil principal et l'équipe de développement en tant que fil de travail. Les threads de l'équipe de développement attendent d'autres threads de l'équipe de développement après avoir terminé leur tâche.
CountDownLatch: Si nous voulons que tous nos threads fassent
quelque chose + compte à rebours
de sorte que autre attente (pour que le compte atteigne zéro) threads peut continuer, nous pouvons utiliser le compte à rebours verrouillé. Tous les threads précédents qui ont réellement effectué le compte à rebours peuvent continuer dans cette situation, mais rien ne garantit que la ligne traitée après latch.countdown () le sera après avoir attendu que d'autres threads parviennent à latch.countdown () une garantie que les autres threads en attente ne démarreront plus que lorsque latch.await () aura atteint zéro.
CyclicBarrier: / Si nous voulons que tout notre fil soit
faire quelque chose + attendre au point commun + faire quelque chose
(chaque appel en attente diminuera le temps d'attente pour que les threads continuent à avancer)
La fonctionnalité CyclicBarrier peut être obtenue par CountDownLatch une seule fois en appelant latch.countdown (), suivie de latch.await () par tous les threads.
mais encore une fois, vous ne pouvez pas réinitialiser/réutiliser le compte à rebours.
Le meilleur exemple dans lequel j'ai utilisé CyclicBarrier est d'initialiser plusieurs caches (réchauffé par plusieurs threads), puis de lancer un traitement supplémentaire, et je voulais réinitialiser d'autres caches à nouveau dans Sync.
Comme son nom l'indique, une barrière cyclique peut être utilisée en cycles. Par exemple, je suis une entreprise qui recherche un nombre N de CV provenant de différents flux de portail d’emploi. J'ai un tableau de compétences contenant des compétences triées par ordre de priorité. Pour ex Java, c #, python. Je veux trouver N reprend les compétences correspondant à Java, mais si je ne trouve pas le numéro requis. de CV, je cherche à nouveau sur la compétence suivante et ainsi de suite.
Je crée un ouvrier qui parcourt chacun des CV dans les flux de travail assignés. Les deux travailleurs commenceront par la recherche de compétences principales dans leur fil d’alimentation.
Après avoir effectué la recherche, le vérificateur vérifiera si les CV ont été trouvés. Si trouvé, le travailleur va réinitialiser la barrière et revenir. Sinon, il attendra que l'autre travailleur ait terminé. Si toujours N curriculum vitae n’était pas trouvé, la recherche serait reprise à la prochaine compétence du tableau des compétences. La recherche peut donc être appelée récursivement/cycliquement sans qu'il soit nécessaire de créer une nouvelle barrière cyclique.