有什么好办法区分虚假唤醒和Thread.interrupt()?

Is there a good way to distinguish spurious wake up and Thread.interrupt()?

我想制作一个可以随时中断的线程,同时防止虚假唤醒。 这里的问题是虚假唤醒和中断的工作方式相同:它们抛出 InterruptedException

void anyMethodCalledByThread() {
  // .. a lot of work before
  while (wakingUpCondition) {
     try {
       lock.wait()
     } catch (InterruptedException e) {
       // is it spurious wake up and I should just ignore it?
       // or is it actual interrupt and I should do:
       // Thread.interrupt();
       // return;
       // and check interruption status in methods above to abort all tasks?
     }
  }
  // .. a lot of work after
}

据我所知,仅jdk是无法区分的,甚至Condition也是no use。我看到的唯一可能的解决方案是每个线程使用一些额外的 volatile boolean,但这使得 Thread.interrupt() 本身基本上没用。

spurious wakes as well as interrupts work the same: they throw InterruptedException

这不是我的理解。 Spurious wakeups 发生是因为在没有明确发出信号的情况下唤醒了一个条件,与 InterruptedException 无关。由于实现细节,当 any 条件发出信号时,某些线程系统会唤醒 all 条件。根据定义,虚假唤醒是我们需要 while 循环的原因之一。

如果 wait() 方法抛出 InterruptedException 那么它真的被中断了。

// we use while loop because lock.wait() might return because of spurious wakeup
while (wakingUpCondition) {
   try {
      lock.wait()
   } catch (InterruptedException ie) {
      // if the wait was interrupted then we should re-interrupt and maybe quit
      Thread.currentThread().interrupt();
      // handle the interrupt by maybe quitting the thread?
      return;
   }
}

顺便说一句,我认为我们较少使用 while 循环来处理虚假唤醒条件(这种情况很少见),而更多地使用 thread race conditions