¿Hay alguna ventaja de usar
java.util.concurrent.CountdownLatch
en vez de
java.util.concurrent.Semaphore ?
Por lo que puedo decir, los siguientes fragmentos son casi equivalentes:
1. Semáforo
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();
Excepto que en el caso n. ° 2, el pestillo no se puede reutilizar y, lo que es más importante, debe saber de antemano cuántos subprocesos se crearán (o esperar hasta que se inicien antes de crear el pestillo).
Entonces, ¿en qué situación sería preferible el pestillo?
CountDownLatch se usa para iniciar una serie de subprocesos y luego esperar hasta que todos estén completos (o hasta que llamen
countDown()
un número determinado de veces.El semáforo se utiliza para controlar el número de subprocesos simultáneos que utilizan un recurso. Ese recurso puede ser algo así como un archivo, o podría ser la CPU al limitar la cantidad de subprocesos que se ejecutan. El recuento de un semáforo puede subir y bajar a medida que diferentes hilos llaman
acquire()
yrelease()
.En su ejemplo, esencialmente está usando Semaphore como una especie de Count UP Latch. Dado que su intención es esperar a que terminen todos los hilos, usar el
CountdownLatch
hace que su intención sea más clara.fuente
Breve resumen:
Semaphore y CountDownLatch tienen un propósito diferente.
Utilice Semaphore para controlar el acceso del hilo al recurso.
Utilice CountDownLatch para esperar la finalización de todos los hilos
Definición de semáforo de javadocs:
Sin embargo, no se utilizan objetos de permiso reales; el semáforo solo lleva un recuento del número disponible y actúa en consecuencia.
Como funciona ?
Los semáforos se utilizan para controlar la cantidad de subprocesos simultáneos que están usando un recurso. Ese recurso puede ser algo así como un dato compartido, un bloque de código ( sección crítica ) o cualquier archivo.
El recuento de un semáforo puede subir y bajar a medida que diferentes hilos llaman
acquire
() yrelease
(). Pero en cualquier momento, no puede tener más subprocesos que el recuento de semáforos.Casos de uso de semáforos:
Eche un vistazo a este artículo para conocer los usos de los semáforos.
CountDownLatch definición de javadocs:
¿Como funciona?
CountDownLatch funciona al tener un contador inicializado con el número de subprocesos, que se reduce cada vez que un subproceso completa su ejecución. Cuando el recuento llega a cero, significa que todos los subprocesos han completado su ejecución y el subproceso que espera en el pestillo reanuda la ejecución.
Casos de uso de CountDownLatch:
Eche un vistazo a este artículo para comprender claramente los conceptos de CountDownLatch.
Eche un vistazo a Fork Join Pool en este artículo también. Tiene algunas similitudes con CountDownLatch .
fuente
Digamos que entró en la tienda de golf con la esperanza de encontrar un cuarteto,
Cuando hace fila para obtener un tee time de uno de los asistentes de la tienda profesional, básicamente llama
proshopVendorSemaphore.acquire()
, una vez que obtiene un tee time, llama.proshopVendorSemaphore.release()
Nota: cualquiera de los asistentes gratuitos puede atenderlo, es decir, recurso compartido.Ahora camina hacia el arranque, comienza un
CountDownLatch(4)
y llamaawait()
para esperar a los demás, por tu parte, llamaste registrado, es decirCountDownLatch
.countDown()
y también el resto del cuarteto. Cuando llegan todos, el motor de arranque da marcha (await()
devuelve la llamada)Ahora, después de nueve hoyos cuando cada uno de ustedes se toma un descanso, hipotéticamente involucremos al abridor nuevamente, él usa un 'nuevo'
CountDownLatch(4)
para comenzar el hoyo 10, la misma espera / sincronización que el hoyo 1.Sin embargo, si el abridor usó un
CyclicBarrier
para empezar, podría haber reiniciado la misma instancia en el hoyo 10 en lugar de un segundo pestillo, que usa & throw.fuente
En cuanto a la fuente disponible gratuitamente, no hay magia en la implementación de las dos clases, por lo que su rendimiento debería ser muy similar. Elija el que haga más obvia su intención.
fuente
CountdownLatch
hace que los subprocesos esperen en elawait()
método, hasta que el recuento llegue a cero. Entonces, tal vez quieras que todos tus hilos esperen hasta 3 invocaciones de algo, entonces todos los hilos pueden irse. UnLatch
general no se puede restablecer.A
Semaphore
permite que los subprocesos recuperen permisos, lo que evita que se ejecuten demasiados subprocesos a la vez, bloqueándose si no puede obtener los permisos que requiere para continuar. Los permisos se pueden devolver paraSemaphore
permitir que los otros hilos en espera continúen.fuente