我正在阅读java.util.concurrent.locks.Condition
API文档,
我明白了:
在等待条件时,允许“虚假唤醒” 通常,作为对底层平台的让步 语义。这对大多数应用程序几乎没有实际影响 程序作为条件应始终在循环中等待, 测试正在等待的状态谓词。一个 实施是免费的,以消除虚假唤醒的可能性 但建议应用程序员始终假设这一点 它们可以发生,因此总是在循环中等待
和awaitUninterruptibly()说:
如果当前线程进入此状态时设置了当前线程的中断状态 方法,或等待时中断,它将继续等待 直到发出信号。当它最终从这个方法返回时它 中断状态仍将设置
那么,是否意味着我们不需要在循环中调用awaitUninterruptibly()?请澄清。提前谢谢。
答案 0 :(得分:3)
specification is pretty clear:
void awaitUninterruptibly()
使当前线程等待直到发出信号。 与此条件关联的锁被原子释放,并且当前线程因线程调度而被禁用,并且处于休眠状态,直到一个三件事情发生:
- 其他一些线程为此Condition调用
signal()
方法,当前线程恰好被选为要被唤醒的线程;或- 其他一些线程为此Condition调用
signalAll()
方法;或- 发生“虚假唤醒”。
因此,中断不在可能的唤醒条件列表中,但是虚假唤醒。不要让您通过查看特定的实现代码来指导。您的应用程序最终运行的实现可能完全不同。
此外,Condition
是interface
,即使在一个运行时环境中也可能有不同的实现。 This answer甚至没有指定此代码来自哪个具体类。
您必须使用awaitUninterruptibly()
的常规循环执行等待操作。
请考虑以下事项:
因此,即使没有虚假的唤醒,也需要在等待之前预先检查并在唤醒后重新检查的循环。
答案 1 :(得分:2)
来自代码:
public final void awaitUninterruptibly() {
Node node = addConditionWaiter();
int savedState = fullyRelease(node);
boolean interrupted = false;
while (!isOnSyncQueue(node)) {
LockSupport.park(this);
if (Thread.interrupted()) interrupted = true;
}
if (acquireQueued(node, savedState) || interrupted) selfInterrupt();
}
所以等待是在一个循环中完成的,这将消除在该函数之外循环的需要。
但是请记住,这也意味着Thread.interrupt()
不会做任何事情,这可能会导致代码的某些锁定,即使用。在关机期间。