Semaphore
adquirir todos los permisos a la vez, de lo contrario no sería un verdadero semaphore. PERO: la versión de Java también tiene una cola de espera interna. Y el comportamiento de esa cola es NOsirve el mejor ajuste de recursos actualmente libres pero más o menos reúne permisos hasta que se pueda permitir la solicitud del primero en la cola. Pero antes de que un hilo ingrese esa cola se realiza una comprobación si los permisos disponibles permiten que el hilo evite entrar en la cola.
he modificado el código para mostrar que el comportamiento de colas:
import java.util.concurrent.*;
public class SemaphoreTest{
static Semaphore s = new Semaphore(0);
public void fun(final char c, final int r) throws Exception {
new Thread(new Runnable(){
public void run(){
try{
System.out.println("acquire "+r);
s.acquire(r);
System.out.println(c+"_"+r);
} catch(Exception e){ e.printStackTrace(); }
}
}).start();
Thread.sleep(500);
}
public static void main(String[]args) throws Exception{
SemaphoreTest f = new SemaphoreTest();
f.fun('B',2);
f.fun('F',6);
f.fun('A',1);
f.fun('C',3);
f.fun('D',4);
f.fun('E',5);
while(s.hasQueuedThreads()){
Thread.sleep(1000);
System.out.println("release "+1+", available "+(s.availablePermits()+1));
s.release(1);
}
}
}
Básicamente los siguientes cambios se han hecho:
- de inicio con 0 permisos - dejar entrar a nadie en la cola primero.
- "Defina" el orden de las colas dando a cada hilo 500ms de tiempo después de
Thread.start
.
- Cada hilo llamará al
acquire
pero no al release
.
- El hilo principal alimentará el semáforo lentamente con un permiso después del otro.
Esto dará a esta salida determinista:
acquire 2
acquire 6
acquire 1
acquire 3
acquire 4
acquire 5
release 1, available 1
release 1, available 2
B_2
release 1, available 1
release 1, available 2
release 1, available 3
release 1, available 4
release 1, available 5
release 1, available 6
F_6
release 1, available 1
A_1
release 1, available 1
release 1, available 2
release 1, available 3
C_3
release 1, available 1
release 1, available 2
release 1, available 3
release 1, available 4
D_4
release 1, available 1
release 1, available 2
release 1, available 3
release 1, available 4
release 1, available 5
E_5
release 1, available 1
Lo que significa que: Cada hilo es despertado, si
- que está en la cabeza de la cola.
- se han acumulado suficientes permisos.
Eso lo arregla, pero me pregunto por qué es necesario. Si se bloquea después de imprimir B_2, y en el hilo principal, después de un tiempo, imprimo el número de permisos disponibles, imprime 3. Entonces, ¿por qué no se permite que el hilo C continúe? – Vlad
@Vlad: Supongo que el '3' no refleja el hecho de que' D' podría haber "reservado" algunos permisos para su llamada 'acquire (4)'. – NPE
Creo que tienes razón. No había leído la documentación con suficiente cuidado. [enlace] (http://download.oracle.com/javase/6/docs/api/java/util/concurrent/Semaphore.html#release (int)). Había asumido que la implementación pasaría por los hilos y trataría de encontrar uno que realmente pudiera despertar. – Vlad