Need to semaphore.relase() if semaphore.acquire() gets InterruptedException?
Asked Answered
R

3

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() ?

Reyesreykjavik answered 24/8, 2012 at 7:31 Comment(0)
A
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();
}
Antique answered 24/8, 2012 at 7:48 Comment(1)
The problem with this is that semaphore.acquire() also throws InterruptedException.Chewy
C
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
}
Chewy answered 21/2, 2014 at 5:23 Comment(4)
Is it really necessary to have nested try catch? Can we acquire and release the semaphore in just one try catch?Calque
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. docs.oracle.com/javase/7/docs/api/java/util/concurrent/…Chewy
Is it okay if I use a generic Exception e case rather than InterruptedException e?Calque
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.Juice
W
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();
}
Westsouthwest answered 24/8, 2012 at 7:55 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.