A seemingly straightforward problem: I have a java.util.concurrent.Semaphore
, and I want to acquire a permit using acquire()
.
The acquire()
method is specified to throw InterruptedException
if the thread is interrupted:
If the current thread:
- has its interrupted status set on entry to this method; or
- is interrupted while waiting for a permit,
then InterruptedException is thrown and the current thread's interrupted status is cleared.
However, the usual pattern with methods that may throw InterruptedException
is to call them in a loop, since threads can be subject to spurious wakeups that look the same as being interrupted. For example, the documentation for Object.wait(long)
says:
A thread can also wake up without being notified, interrupted, or timing out, a so-called spurious wakeup. While this will rarely occur in practice, applications must guard against it by testing for the condition that should have caused the thread to be awakened, and continuing to wait if the condition is not satisfied. In other words, waits should always occur in loops.
So the question is, is Semaphore.acquire()
subject to the same kind of spurious wakeup? The logical answer would be "no", but I can't find any evidence for that, and in fact the evidence seems to point in the other direction.
Looking at the source for Semaphore
, it appears that it delegates the actual acquire to an AbstractQueuedSynchronizer
, which according to its source delegates to LockSupport.park()
.
The documentation for LockSupport.park()
explicitly mentions spurious wakeup, but the implementation of AbstractQueuedSynchronizer.doAcquireInterruptably()
appears to just check Thread.interrupted()
and then throw InterruptedException
.
So, unless I'm missing something (which is very possible), it appears that Semaphore.acquire()
can throw InterruptedException
spuriously?
Is that correct? More importantly, is there anything I can do about that? I could use Semaphore.acquireUninterruptably()
, but I don't want an uninterruptable wait, just one that doesn't get interrupted spuriously. Is there any alternative?
It is "spurious wakeup" not "spurious interrupt": "A thread can also wake up without being notified, interrupted, or timing out, a so-called spurious wakeup." There is no InterruptedException thrown during a spurious wakeup. As you say in the comments: The thread wakes up but the interrupted flag is not set.
I think if you think about the Semaphore.acquire()
API, you'll realize that it's impossible for it to have a spurious wakeup, mainly because the caller would have no way to distinguish "spurious" for "normal", and therefore the method would be useless.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With