使用java.util.concurrent类时,我应该何时担心虚假唤醒

时间:2014-04-29 18:09:49

标签: java multithreading synchronization

我知道如果我调用Object.wait()我必须考虑虚假的唤醒,所以我应该将等待包裹在循环,以检查我的实际情况达到了终止条件。但是在我使用java.util.concurrent.*类的情况下,我还应该担心吗?

我正在使用 java.util.concurrent.BlockingQueue ,我想知道我什么时候queue.take()我希望有时 take()因为虚假的唤醒(InterruptedException)而停止阻塞,而不是因为它实际上从队列中读取了一些内容。换句话说,如果虚假唤醒是一种风险,我需要捕获实际检查终止的InterruptedException INSIDE while循环。如果它们不是,那么我应该让InterruptedExceptions打破主循环并在我得到一个时停止处理

或代码

@Override
public void run() {
  while(running()) {
    try {
       queue.take();
    } catch (InterruptedException exc) {
       log.warn("Spurious wakeup, ignore and try again");
    }
  }
}

VS

@Override
public void run() {
  try {
    while(running()) {
       queue.take();
    }
  } catch (InterruptedException exc) {
      log.error("Some other reason for InterruptedException, finish thread");
  }
}

1 个答案:

答案 0 :(得分:2)

离开这个问题:Can Semaphore.acquire() throw InterruptedException due to a spurious wakeup?

看起来虚假的唤醒实际上并没有打断线程,所以看起来你不需要在那里尝试/捕获(编辑:对于一个虚假的唤醒,那个如果等待线程实际被中断,你仍然需要它。

根据第一个答案:

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