在while循环中检查wait()的条件是什么?

时间:2018-02-12 10:54:34

标签: java multithreading

我正在学习Java中的多线程编程,最困难的部分似乎是使用wait()notify()notifyAll()进行线程间通信。

我提到wait()的官方Javadoc,在这里复制:

 synchronized (obj) {
     while (<condition does not hold>)
         obj.wait();
     ... // Perform action appropriate to condition
 }

我明白当线程t调用wait()时,它会立即释放锁,然后等待;但是我无法理解while loop中的条件是什么意思?线程t检查while loop条件是否被某个其他线程修改之前,是否有可能存在机会?

有谁可以告诉我这个condition是什么以及在while循环中使用哪些基本内容来检查条件?

4 个答案:

答案 0 :(得分:2)

您不仅需要循环它,还要检查循环中的条件。 Java不保证您的线程只能通过notify()/ notifyAll()调用或正确的notify()/ notifyAll()调用来唤醒。由于此属性,无环版本可能适用于您的开发环境,并且意外地在生产环境中失败。

例如,您正在等待某事:

synchronized (theObjectYouAreWaitingOn) {
   while (!carryOn) {
      theObjectYouAreWaitingOn.wait();
   }
}

邪恶的线索出现了:

theObjectYouAreWaitingOn.notifyAll(); 如果邪恶的线程没有/不能使用carryOn,你只需继续等待合适的客户端。

编辑:添加了一些样本。等待可以中断。它抛出InterruptedException,你可能需要在try-catch中包装wait。根据您的业务需求,您可以退出或取消异常并继续等待。

检查下面的一个也是为了更清晰。

等待和通知用于实现[条件变量](http://en.wikipedia.org/wiki/Monitor_(synchronization)#Blocking_condition_variables),因此您需要在继续之前检查您等待的特定谓词是否为真。

答案 1 :(得分:2)

问题是obj可能会通过obj.notifyAll()调用所有等待的线程,这些被唤醒的线程将以不确定的顺序进入同步代码块,并操作共享数据。因此,有必要在while循环中检查条件。

假设你有一个空队列,thread1和thread2正在等待从中获取元素,

 synchronized (obj) {
     while (queue.isEmpty())
         obj.wait();
     ... // Perform action appropriate to condition
     queue.take();
 }

在thread3中放入一个元素后,调用obj.notifyAll(),调用thread1和thread2:

  • thread1首先唤醒,找到队列中唯一的元素,然后接受它。
  • thread2稍后唤醒,检查queue.isEmpty()wait()队列中是否有任何元素 试。

答案 2 :(得分:1)

condition循环标题中的while可以是在boolean中解析的任何表达式。

在您的示例中,while循环应暂停执行实际方法,直到某个条件为true

假设您的synchronized方法需要在中午12点执行,并且需要线程安全访问对象obj

然后你while循环的头部将检查当前时间是否不是12pm。如果这是true,则该方法无法启动它的实际工作。但是为了防止阻止资源,它将允许其他线程通过调用objobj.wait()一起使用。 当我们到达下午12点时,while循环的条件将为false,并且该线程存在while循环并执行其余代码。

答案 3 :(得分:1)

  

我无法理解while循环中的条件是什么意思?

从字面上看,它意味着你正在等待发生的条件的逻辑逆。

  

在线程t检查while循环中的条件之前是否有机会某个其他线程修改了条件?

假设 1 是构成&#34;条件的变量&#34;只有在obj 上持有锁时,另一个线程才会更新。

因此,在while循环之后的那一点,上面代码中的线程知道条件现在为真,并且在释放锁之前没有其他任何东西会改变它。

现在......很明显......如果某个其他线程要改变组成条件而没有持有锁的变量,那么你担心的可以发生了。但这是一个有缺陷的计划。您有共享变量由不同的线程更新,没有足够的 2 同步。

1 - 线程在调用obj.notify()obj.notifyAll()时必须持有该锁定。 (如果没有,您将获得异常。)但是,如果变量在单独的同步块中更新为通知调用,则保护条件也将起作用。它只是让代码更难理解......

2 - 在这种情况下,将变量声明为volatile对于保护条件的正确行为是不够的。