2012-08-24 16 views
8

Desde Java java.util.concurrent.Semaphore docs, no estaba del todo claro para mí qué sucede si semáforo.acquire() bloquea el hilo y luego es interrumpido por una InterruptedException. ¿Se ha disminuido el valor del semáforo y, por lo tanto, existe la necesidad de liberar el semáforo?Necesita semaphore.relase() si semaphore.acquire() obtiene InterruptedException?

Actualmente estoy usando código como este:

try { 
    // use semaphore to limit number of parallel threads 
    semaphore.acquire(); 
    doMyWork(); 
} 
finally { 
    semaphore.release(); 
} 

o debería prefieren no llamar la liberación() cuando se produce un InterruptedException durante la adquisición()?

Respuesta

8

liberación de llamada() cuando se produce una interruptedException durante la adquisición()?

No debe. Si se interrumpe .acquire(), el semáforo no se adquiere, por lo que es probable que no lo libere.

El código debería ser

// use semaphore to limit number of parallel threads 
semaphore.acquire(); 
try { 
    doMyWork(); 
} 
finally { 
    semaphore.release(); 
} 
+0

Gracias, eso suena muy razonable. Cambiaré mi código como sugirió. – kasimir

+5

El problema con esto es que semáforo.acquire() también arroja InterruptedException. – jblack

0

Si el hilo se interrumpe antes llamada al método adquieren, o mientras espera para adquirir un permiso será lanzado el InterruptedException y sin permiso se mantenga, por lo que no hay necesidad de liberar. Solo cuando esté seguro de que se adquirió un permiso (después de llamar a la llamada de método adquirido) deberá liberar el permiso. Así se adquiere mejor antes de su bloque se inicia intento, algo así como:

sem.acquire(); 
try{ 
    doMyWork(); 
}finally{ 
    sem.release(); 
} 
3

núms del aceptados respuesta es parcialmente correcto, excepto semaphore.acquire() también lanza InterruptedException. Entonces, para ser 100% correcto, el código se vería así:

try { 
    semaphore.acquire(); 
    try { 
     doMyWork(); 
    } catch (InterruptedException e) { 
     // do something, if you wish 
    } finally { 
     semaphore.release(); 
    } 
} catch (InterruptedException e) { 
    // do something, if you wish 
} 
+0

¿Es realmente necesario anidar la captura de prueba? ¿Podemos adquirir y liberar el semáforo en solo una captura de prueba? – Joyce

+2

Suponiendo que desea manejar correctamente el caso cuando la llamada a semáforo.acquire() arroja una excepción InterruptedException, las capturas de prueba anidadas son necesarias. InterruptedException se puede lanzar tanto durante la llamada a semáforo.acquire() como después de que se haya adquirido. http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/Semaphore.html#acquire() – jblack

+0

¿Está bien si uso un caso genérico de 'Exception e' en lugar de' InterruptedException e ¿? – Joyce

Cuestiones relacionadas