当我读java.util.concurrent.locks.Condition
API文档,
我看到:
在审批条件等,“虚假唤醒”被允许发生,一般来说,作为让步的基础平台语义。 这有一个条件应该总是在一个循环等待,测试正被等待的状态谓词在大多数应用程序的实际影响很小。 实现是免费删除虚假唤醒的可能性,但建议应用程序的程序员总是假定他们可以发生,所以在循环总是等待
和awaitUninterruptibly()说:
如果当它进入这个方法,或者是在等待中断了当前线程的中断状态设置,将继续等待,直到信号。 当它终于从这个方法返回的中断状态仍然会设置
那么,这是否意味着我们不需要在循环调用awaitUninterruptibly()? 请澄清。 提前致谢。
从代码:
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()
不会做任何事情,关闭过程中可能导致你的代码,即一定的禁售期。
该规范是相当清楚的 :
void awaitUninterruptibly()
造成当前线程在等待,直到它发出信号。 与此条件相关的锁以原子方式释放,并且当前线程的线程调度目的就退出,一直处于休眠状态的三种情况之一发生:
- 一些其它线程调用
signal()
方法为这个条件和当前的线程正好被选择作为被唤醒线程; 要么 - 一些其它线程调用
signalAll()
此条件的方法; 要么 - “ 虚假唤醒 ”的发生。
所以,打断是不是可能的唤醒条件,但虚假唤醒名单上。 不要让你通过寻找到一条特定的实现代码指导。 您的应用程序终于可以运行在实施可能会完全不同。
此外, Condition
是interface
可能甚至在一个运行环境有不同的实现。 这个答案甚至不指定具体类的代码是从。
您可以使用通常的循环与执行等待操作awaitUninterruptibly()
考虑以下:
- 没有1:信号并等待1之间的映射,
- 因此,你可能会错过之前你的线程醒来时发生一个或多个信号
- 更糟的是,信号不被记住,因而失去了当他们发生之前另一个线程开始等待
- 因此,你必须决定要等待之前预先检查所需的条件状态
- 这意味着一个信号可能会唤醒一个线程,但另一个消耗状态因为有成功的前检查,因此该醒了线程必须重新检查所需的条件状态
因此,即使没有杂散唤醒一个环路,它睡醒后等待并重新检查之前预先检查是必要的。