2012-08-24 14 views
8

Dai documenti Java java.util.concurrent.Semaphore non mi era chiaro cosa succederà se semaphore.acquire() blocca il thread e successivamente viene interrotto da un'interruzione di interrupt. Il valore del semaforo è diminuito e quindi è necessario rilasciare il semaforo?Hai bisogno di semaphore.relase() se semaphore.acquire() ottiene InterruptedException?

Attualmente sto usando il codice come questo:

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

o non dovrebbe preferisco chiamare Release() quando si verifica un InterruptedException durante l'acquisizione()?

risposta

8

rilascio di chiamata() quando si verifica un'interruptupException durante l'acquisizione()?

Non si dovrebbe. Se .acquire() viene interrotto, il semaforo non viene acquisito, quindi probabilmente non dovrebbe rilasciarlo.

Il codice dovrebbe essere

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

Grazie, sembra molto ragionevole. Cambierò il mio codice come mi hai suggerito. – kasimir

+5

Il problema con questo è che semaphore.acquire() genera anche InterruptedException. – jblack

0

Se il filo si interrompe prima che il metodo acquisiscono chiamata, o in attesa di acquisire un permesso l'InterruptedException sarà gettato e nessun permesso sarà tenere, quindi nessun bisogno di rilasciare. Solo quando si è certi che è stato acquisito un permesso (dopo aver chiamato la chiamata al metodo di acquisizione) è necessario rilasciare il permesso. Quindi è meglio acquisire davanti ai vostri blocco inizia provare, qualcosa di simile a:

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

nos accettato risposta è parzialmente corretta, tranne semaphore.acquire() genera anche InterruptedException. Quindi, per essere corretto al 100%, il codice sarà simile a:

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

È davvero necessario avere il try annidato? Possiamo acquisire e rilasciare il semaforo in un solo tentativo? – Joyce

+2

Supponendo di voler gestire con garbo il caso quando la chiamata a semaphore.acquire() genera un InterruptedException, i try-catch annidati sono necessari. InterruptedException può essere lanciata sia durante la chiamata a semaphore.acquire() che dopo che è stata acquisita. http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/Semaphore.html#acquire() – jblack

+0

Va bene se utilizzo un caso generico 'Exception e' invece di' InterruptedException e '? – Joyce