14

From the Java java.util.concurrent.Semaphore docs it wasn't quite clear to me what happens if semaphore.acquire() blocks the thread and later gets interrupted by an InterruptedException. Has the semaphore value been decreased and so is there a need to release the semaphore?

Currently I am using code like this:

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

Or should I rather not call release() when an InterruptedException occurs during acquire() ?

Ernie
  • 1,210
  • 1
  • 14
  • 21

3 Answers3

13

call release() when an InterruptedException occurs during acquire() ?

You should not. If .acquire() is interrupted, the semaphore is not acquired, so likely should not release it.

Your code should be

// use semaphore to limit number of parallel threads
semaphore.acquire();
try {
  doMyWork();
}
finally {
  semaphore.release();
}
nos
  • 223,662
  • 58
  • 417
  • 506
8

nos's accepted answer is partially correct, except semaphore.acquire() also throws InterruptedException. So, to be 100% correct, the code would look like:

try {
    semaphore.acquire();
    try {
        doMyWork();
    } catch (InterruptedException e) { 
        // do something, if you wish
    } finally {
        semaphore.release();
    }
} catch (InterruptedException e) {
    // do something, if you wish
}
jblack
  • 821
  • 8
  • 14
  • 1
    Is it really necessary to have nested try catch? Can we acquire and release the semaphore in just one try catch? – Joyce Apr 03 '14 at 20:34
  • 2
    Assuming you want to gracefully handle the case when the call to semaphore.acquire() throws an InterruptedException, the nested try-catches are necessary. InterruptedException can be thrown both during the call to semaphore.acquire() and after it has been acquired. http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/Semaphore.html#acquire() – jblack Apr 04 '14 at 14:45
  • Is it okay if I use a generic `Exception e` case rather than `InterruptedException e`? – Joyce Apr 04 '14 at 18:13
  • 5
    There is no special reason why `doMyWork()` would want to throw an `InterruptedException`. A code that is not waiting for something and just performs a non-blocking task is not throwing `InterruptedException`'s. So the inner try could just have a finally clause and no catch. – Nytux Mar 18 '15 at 15:37
0

If the thread is interrupted before acquire method call, or while waiting to acquire a permit the InterruptedException will be thrown and no permit will be hold, so no need to release. Only when you are certain that a permit was acquired (after calling the acquire method call) you will need to release the permit. So you better acquire before your try block starts, something like:

sem.acquire();
try{
   doMyWork();
}finally{
   sem.release();
}
dan
  • 13,132
  • 3
  • 38
  • 49