Y a-t-il un avantage à utiliser
java.util.concurrent.CountdownLatch
au lieu de
java.util.concurrent.Semaphore ?
Pour autant que je sache, les fragments suivants sont presque équivalents:
1. Sémaphore
final Semaphore sem = new Semaphore(0);
for (int i = 0; i < num_threads; ++ i)
{
Thread t = new Thread() {
public void run()
{
try
{
doStuff();
}
finally
{
sem.release();
}
}
};
t.start();
}
sem.acquire(num_threads);
2: CountDownLatch
final CountDownLatch latch = new CountDownLatch(num_threads);
for (int i = 0; i < num_threads; ++ i)
{
Thread t = new Thread() {
public void run()
{
try
{
doStuff();
}
finally
{
latch.countDown();
}
}
};
t.start();
}
latch.await();
Sauf que dans le cas n ° 2, le verrou ne peut pas être réutilisé et, plus important encore, vous devez savoir à l'avance combien de threads seront créés (ou attendre qu'ils soient tous démarrés avant de créer le verrou.)
Dans quelle situation le loquet serait-il préférable?
CountDownLatch est utilisé pour démarrer une série de threads, puis attendre qu'ils soient tous terminés (ou jusqu'à ce qu'ils appellent
countDown()
un nombre donné de fois.Le sémaphore est utilisé pour contrôler le nombre de threads simultanés qui utilisent une ressource. Cette ressource peut être quelque chose comme un fichier, ou pourrait être le processeur en limitant le nombre de threads en cours d'exécution. Le décompte d'un sémaphore peut augmenter et diminuer lorsque différents threads appellent
acquire()
etrelease()
.Dans votre exemple, vous utilisez essentiellement Semaphore comme une sorte de Count UP Latch. Étant donné que votre intention est d'attendre la fin de tous les threads, l'utilisation de
CountdownLatch
rend votre intention plus claire.la source
Court résumé:
Semaphore et CountDownLatch ont des objectifs différents.
Utilisez Semaphore pour contrôler l'accès des threads aux ressources.
Utilisez CountDownLatch pour attendre la fin de tous les threads
Définition de sémaphore de javadocs:
Cependant, aucun objet de permis réel n'est utilisé; le sémaphore tient simplement un compte du nombre disponible et agit en conséquence.
Comment ça marche ?
Les sémaphores sont utilisés pour contrôler le nombre de threads simultanés qui utilisent une ressource.Cette ressource peut être quelque chose comme des données partagées ou un bloc de code ( section critique ) ou n'importe quel fichier.
Le décompte d'un sémaphore peut augmenter et diminuer lorsque différents threads appellent
acquire
() etrelease
(). Mais à tout moment, vous ne pouvez pas avoir plus de threads supérieur au nombre de sémaphore.Cas d'utilisation de sémaphore:
Jetez un œil à cet article pour les utilisations de sémaphore.
CountDownLatch définition de javadocs:
Comment ça marche?
CountDownLatch fonctionne en ayant un compteur initialisé avec le nombre de threads, qui est décrémenté chaque fois qu'un thread termine son exécution. Lorsque le nombre atteint zéro, cela signifie que tous les threads ont terminé leur exécution et que les threads en attente de verrouillage reprennent l'exécution.
CountDownLatch Cas d'utilisation:
Consultez cet article pour comprendre clairement les concepts de CountDownLatch.
Jetez également un œil à Fork Join Pool dans cet article . Il présente quelques similitudes avec CountDownLatch .
la source
Disons que vous êtes entré dans la boutique de golf pro, dans l'espoir de trouver un quatuor,
Lorsque vous faites la queue pour obtenir une heure de départ de l'un des préposés de la boutique professionnelle, vous avez essentiellement appelé
proshopVendorSemaphore.acquire()
, une fois que vous avez obtenu une heure de départ, vous avez appeléproshopVendorSemaphore.release()
Remarque: n'importe lequel des agents gratuits peut vous servir, c'est-à-dire une ressource partagée.Maintenant vous marchez vers le démarreur, il commence un
CountDownLatch(4)
et appelleawait()
pour attendre les autres, pour votre part vous avez appelé check-in ieCountDownLatch
.countDown()
et le reste du quatuor aussi. Quand tout arrive, le démarreur donne le feu (await()
appel revient)Maintenant, après neuf trous lorsque chacun de vous fait une pause, laisse hypothétiquement impliquer à nouveau le démarreur, il utilise un `` nouveau ''
CountDownLatch(4)
pour jouer au trou 10, même attente / synchronisation que le trou 1.Cependant, si le starter a utilisé un
CyclicBarrier
pour commencer, il aurait pu réinitialiser la même instance dans le trou 10 au lieu d'un deuxième verrou, qui utilise & throw.la source
En regardant la source disponible gratuitement, il n'y a pas de magie dans l'implémentation des deux classes, donc leurs performances devraient être sensiblement les mêmes. Choisissez celui qui rend votre intention plus évidente.
la source
CountdownLatch
fait attendre les threads sur laawait()
méthode, jusqu'à ce que le nombre atteigne zéro. Alors peut-être que vous voulez que tous vos threads attendent jusqu'à 3 invocations de quelque chose, alors tous les threads peuvent partir. UnLatch
ne peut généralement pas être réinitialisé.A
Semaphore
permet aux threads de récupérer les autorisations, ce qui empêche trop de threads de s'exécuter à la fois, bloquant s'il ne peut pas obtenir les autorisations nécessaires pour continuer. LesSemaphore
autorisations peuvent être retournées à un, ce qui permet aux autres threads en attente de continuer.la source