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

标签 java semaphore java.util.concurrent

一个看似简单的问题:我有一个 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/

相关文章:

java - 使用正则表达式过滤器聚合 MongoDB Java 驱动程序

C - 信号量未在所有进程上共享

c# - 命名信号量名称的最大长度是多少?

java - 执行者完成服务?如果我们有invokeAll,为什么还需要一个?

multithreading - Condition 的哪些实现不需要当前线程持有锁?

java - 哪个并发列表适合多个作者一个读者?

java - 如何获取 XSOM Java 库中的 Use Attribute

java - 位图创建内存不足

java - Jhipster 上的两个 MySQL 数据库

php信号量不起作用