首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >java.util.concurrent.locks.Condition awaitUninterruptibly()

java.util.concurrent.locks.Condition awaitUninterruptibly()
EN

Stack Overflow用户
提问于 2015-01-14 07:53:39
回答 2查看 1.1K关注 0票数 1

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

我看到:

在等待条件时,通常允许出现“虚假唤醒”,作为对底层平台语义的让步。这对大多数应用程序几乎没有实际影响,因为应该始终在循环中等待条件,测试等待的状态谓词。实现可以自由地消除出现虚假唤醒的可能性,但建议应用程序程序员始终假定它们可以发生,因此总是在循环中等待。

awaitUninterruptibly()说:

如果当前线程的中断状态是在它进入此方法时设置的,或者它在等待时被中断,则它将继续等待直到发出信号。当它最终从该方法返回时,它的中断状态仍将被设置。

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

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2015-01-14 10:15:54

根据守则:

代码语言:javascript
复制
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()不会做任何事情,这可能会导致代码的某些锁,即在关闭期间。

票数 2
EN

Stack Overflow用户

发布于 2015-01-16 12:04:36

The 规格很清楚

void awaitUninterruptibly() 导致当前线程等待,直到发出信号。与此条件关联的锁被原子释放,当前线程将被禁用以用于线程调度,并处于休眠状态,直到发生以下三种情况之一:

  • 其他一些线程针对此条件调用signal()方法,而当前线程恰好被选择为要唤醒的线程;或
  • 其他一些线程会针对此条件调用signalAll()方法;或
  • 出现“虚假唤醒”。

因此,中断并不在可能的唤醒条件列表中,而是虚假的唤醒条件列表中。不要让您通过查看特定的实现代码来进行指导。您的应用程序最终运行的实现可能完全不同。

此外,Condition是一个interface,即使在一个运行时环境中也可能有不同的实现。这个答案甚至没有指定这段代码来自哪个具体类。

您必须使用通常的awaitUninterruptibly()循环来执行等待操作。

请考虑以下几点:

  • 信号和等待之间没有1:1的映射,
    • 因此,您可能会错过线程醒来前发生的一个或多个信号。
    • 更糟糕的是,当信号发生在另一个线程开始等待之前,信号就不会被记住,因此就会丢失。

  • 因此,在决定等待之前,您必须预先检查所需的条件状态。
  • 这意味着信号可能唤醒一个线程,而另一个线程由于预检查成功而消耗状态,因此唤醒的线程必须重新检查所需的条件状态。

因此,即使没有虚假的唤醒,在等待之前预先检查,醒来后再检查的循环也是必要的。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/27938145

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档