由于虚假的唤醒,Semaphore.acquire()会抛出InterruptedException吗?

Dan*_*den 10 java semaphore java.util.concurrent

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

如果线程被中断,acquire()则指定该方法抛出InterruptedException:

如果当前线程:

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

然后抛出InterruptedException并清除当前线程的中断状态.

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

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

所以问题是,是否Semaphore.acquire()受到同样的虚假唤醒?合乎逻辑的答案是"不",但我找不到任何证据,实际上证据似乎指向了另一个方向.

查看源代码Semaphore,它似乎将实际的获取委托给a AbstractQueuedSynchronizer,根据其来源代表LockSupport.park().

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

所以,除非我遗漏了某些东西(这是非常可能的),否则看起来可能Semaphore.acquire() 抛出InterruptedException虚假的东西?

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

Ski*_*ead 7

它是"虚假唤醒"而非"虚假中断":"线程也可以在没有被通知,中断或超时的情况下唤醒,即所谓的虚假唤醒." 在虚假唤醒期间没有抛出InterruptedException.正如你在评论中所说:线程醒来但是没有设置中断的标志.