一个看似简单的问题:我有一个 java.util.concurrent.Semaphore
,我想使用 acquire()
获得许可证.
acquire()
方法被指定为在线程被中断时抛出 InterruptedException
:
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.
但是,可能抛出 InterruptedException
的方法的通常模式是在循环中调用它们,因为线程可能会受到看起来与被中断相同的虚假唤醒。例如,documentation for Object.wait(long)
说:
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.
所以问题是,Semaphore.acquire()
是否会受到相同类型的虚假唤醒?合乎逻辑的答案是“不”,但我找不到任何证据,事实上证据似乎指向另一个方向。
查看 source for Semaphore
, 它似乎将实际获取委托(delegate)给 AbstractQueuedSynchronizer
, 根据its source委托(delegate)给 LockSupport.park()
。
documentation for LockSupport.park()
明确提到虚假唤醒,但 AbstractQueuedSynchronizer.doAcquireInterruptably()
的实现似乎只是检查 Thread.interrupted()
然后抛出 InterruptedException
。
所以,除非我遗漏了什么(这是很有可能的),否则 Semaphore.acquire()
可以 抛出 InterruptedException
假的?
这样对吗?更重要的是,我能做些什么吗?我可以使用 Semaphore.acquireUninterruptably()
,但我不想要一个不间断的等待,只是一个不会被虚假中断的等待。有其他选择吗?
最佳答案
是“spurious wakeup”而不是“spurious interrupt”:“线程也可以在未被通知、未被中断、未超时的情况下被唤醒,即所谓的spurious wakeup。”在虚假唤醒期间不会抛出 InterruptedException。正如您在评论中所说:线程唤醒但未设置中断标志。
关于java - Semaphore.acquire() 会因虚假唤醒而抛出 InterruptedException 吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12165030/