【问题标题】:When should I worry about spurious wakeups when using java.util.concurrent classes使用 java.util.concurrent 类时,我什么时候应该担心虚假唤醒
【发布时间】:2014-04-29 18:09:49
【问题描述】:

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

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

或者在代码中

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

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

【问题讨论】:

  • 来自链接问题的第一个答案:“InterruptedException 基本上是该线程终止的礼貌请求。线程应尽快清理并退出。”
  • 我不认为你指向的问题与这个问题重复。我的问题是,在使用 java.util.concurrent.* 类时我应该担心虚假唤醒吗?这应该有一个是或否的答案。链接的问题确实为我提供了新信息,所以谢谢
  • 你应该担心并终止线程。链接的第一个答案确实回答了这个问题,CountDownLatch 也是 java.util.concurrent。
  • CountDownLatch.await()和BlockingQueue.take()的等待函数的内容是一样的,所以同样的答案。

标签: java multithreading synchronization


【解决方案1】:

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

看起来虚假唤醒实际上并没有中断线程,所以看起来你不需要在那里尝试/捕获(编辑:对于虚假唤醒,也就是说。你仍然需要它以防等待线程被实际中断)。

根据那里的第一个答案:

"是"伪唤醒"而不是"伪中断":"线程也可以在没有被通知、中断或超时的情况下唤醒,即所谓的伪唤醒。"在伪唤醒期间不会抛出 InterruptedException .正如你在cmets中所说:线程唤醒但未设置中断标志”

【讨论】:

  • 无论如何你都必须处理中断异常。
  • 没错,我只是在考虑虚假唤醒,而不是其他形式的中断。固定的。谢谢!
  • @user3580294 唤醒不是一种“中断形式”,至少对 Java 程序员而言不是这样。在 JVM 或操作系统中可能会发生“中断”之类的事情,但在 Java 层面,它们是两个不同的概念。
猜你喜欢
  • 2011-09-22
  • 1970-01-01
  • 2012-01-25
  • 2011-06-07
  • 1970-01-01
  • 1970-01-01
  • 2019-12-26
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多