Semaphore.acquire() 会因为虚假唤醒而抛出 InterruptedException 吗?



一个看似简单的问题:我有一个java.util.concurrent.Semaphore,我想使用acquire()获得许可证。

acquire() 方法指定在线程中断时引发InterruptedException

如果当前线程:

  • 在进入此方法时设置了中断状态;或
  • 在等待许可证时被打断,

然后抛出中断异常,并清除当前线程的中断状态。

但是,可能引发InterruptedException的方法的常见模式是在循环中调用它们,因为线程可能会受到虚假唤醒的影响,这些唤醒看起来与被中断相同。 例如,Object.wait(long)的文档说:

线程也可以在不被通知、中断或超时的情况下唤醒,即所谓的虚假唤醒。虽然这在实践中很少发生,但应用程序必须通过测试应该导致线程被唤醒的条件来防止它,并在条件不满足时继续等待。换句话说,等待应始终在循环中发生。

那么问题来了,Semaphore.acquire()会受到同样的虚假唤醒吗? 合乎逻辑的答案是否定的,但我找不到任何证据,事实上,证据似乎指向另一个方向。

Semaphore的来源来看,它似乎将实际的获取委托给一个AbstractQueuedSynchronizer,根据其来源委托给LockSupport.park()

LockSupport.park()的文档明确提到了虚假唤醒,但AbstractQueuedSynchronizer.doAcquireInterruptably()的实现似乎只是检查Thread.interrupted()然后抛出InterruptedException

所以,除非我错过了什么(这是很有可能的(,否则Semaphore.acquire()似乎可以虚假地扔InterruptedException

这是对的吗? 更重要的是,我能做些什么吗? 我可以使用Semaphore.acquireUninterruptably(),但我不想要不间断的等待,只是不被虚假打断的等待。 还有其他选择吗?

它是

"虚假唤醒"而不是"虚假中断":"线程也可以在没有通知、中断或超时的情况下唤醒,这就是所谓的虚假唤醒。在虚假唤醒期间不会引发中断异常。正如您在评论中所说:线程唤醒,但未设置中断标志。

我认为

如果你考虑一下Semaphore.acquire() API,你会意识到它不可能有一个虚假的唤醒,主要是因为调用者无法区分"虚假"和"正常",因此该方法将毫无用处。

相关内容

  • 没有找到相关文章

最新更新