java.util.concurrent.locks.Condition中awaitUninterr

2019-10-21 14:13发布

当我读java.util.concurrent.locks.Condition API文档,

我看到:

在审批条件等,“虚假唤醒”被允许发生,一般来说,作为让步的基础平台语义。 这有一个条件应该总是在一个循环等待,测试正被等待的状态谓词在大多数应用程序的实际影响很小。 实现是免费删除虚假唤醒的可能性,但建议应用程序的程序员总是假定他们可以发生,所以在循环总是等待

和awaitUninterruptibly()说:

如果当它进入这个方法,或者是在等待中断了当前线程的中断状态设置,将继续等待,直到信号。 当它终于从这个方法返回的中断状态仍然会设置

那么,这是否意味着我们不需要在循环调用awaitUninterruptibly()? 请澄清。 提前致谢。

Answer 1:

从代码:

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()不会做任何事情,关闭过程中可能导致你的代码,即一定的禁售期。



Answer 2:

该规范是相当清楚的 :

void awaitUninterruptibly()

造成当前线程在等待,直到它发出信号。 与此条件相关的锁以原子方式释放,并且当前线程的线程调度目的就退出,一直处于休眠状态的三种情况之一发生:

  • 一些其它线程调用signal()方法为这个条件和当前的线程正好被选择作为被唤醒线程; 要么
  • 一些其它线程调用signalAll()此条件的方法; 要么
  • 虚假唤醒 ”的发生。

所以,打断是不是可能的唤醒条件,但虚假唤醒名单上。 不要让你通过寻找到一条特定的实现代码指导。 您的应用程序终于可以运行在实施可能会完全不同。

此外, Conditioninterface可能甚至在一个运行环境有不同的实现。 这个答案甚至不指定具体类的代码是从。

您可以使用通常的循环与执行等待操作awaitUninterruptibly()

考虑以下:

  • 没有1:信号并等待1之间的映射,
    • 因此,你可能会错过之前你的线程醒来时发生一个或多个信号
    • 更糟的是,信号不被记住,因而失去了当他们发生之前另一个线程开始等待
  • 因此,你必须决定要等待之前预先检查所需的条件状态
  • 这意味着一个信号可能会唤醒一个线程,但另一个消耗状态因为有成功的前检查,因此该醒了线程必须重新检查所需的条件状态

因此,即使没有杂散唤醒一个环路,它睡醒后等待并重新检查之前预先检查是必要的。



文章来源: java.util.concurrent.locks.Condition awaitUninterruptibly()