Java 在while循环中签入wait()的条件是什么?

Java 在while循环中签入wait()的条件是什么?,java,multithreading,Java,Multithreading,我正在学习Java中的多线程编程,最困难的部分似乎是线程间通信,使用wait、notify和notifyAll 我提到了官方的Javadoc,在这里复制: synchronized (obj) { while (<condition does not hold>) obj.wait(); ... // Perform action appropriate to condition } 我明白了当线程t调用wait时,它会立即释放锁,然后等待

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

我提到了官方的Javadoc,在这里复制:

 synchronized (obj) {
     while (<condition does not hold>)
         obj.wait();
     ... // Perform action appropriate to condition
 }
我明白了当线程t调用wait时,它会立即释放锁,然后等待;然而,我无法理解while循环中的条件意味着什么?当循环中的条件被其他线程修改时,线程t检查该条件之前是否有机会


有人能告诉我这个条件是什么,在while循环中检查条件需要使用哪些基本的东西吗?

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

例如,您正在等待某事:

synchronized (theObjectYouAreWaitingOn) {
   while (!carryOn) {
      theObjectYouAreWaitingOn.wait();
   }
}
一条邪恶的线索出现了:

您正在等待的对象通知所有人; 如果邪恶的线程没有/不能弄乱携带,你只需继续等待合适的客户端

编辑:添加了更多示例。等待可以被中断。它抛出InterruptedException,您可能需要用try-catch来结束等待。根据业务需要,您可以退出或抑制异常并继续等待

检查下面的一个也为您更好的清晰度


wait和notify用于实现[condition variables],因此在继续之前,您需要检查正在等待的特定谓词是否为true。

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

例如,您正在等待某事:

synchronized (theObjectYouAreWaitingOn) {
   while (!carryOn) {
      theObjectYouAreWaitingOn.wait();
   }
}
一条邪恶的线索出现了:

您正在等待的对象通知所有人; 如果邪恶的线程没有/不能弄乱携带,你只需继续等待合适的客户端

编辑:添加了更多示例。等待可以被中断。它抛出InterruptedException,您可能需要用try-catch来结束等待。根据业务需要,您可以退出或抑制异常并继续等待

检查下面的一个也为您更好的清晰度

wait和notify用于实现[condition variables],因此在继续之前,您需要检查您正在等待的特定谓词是否为true。

问题是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 up:

thread1首先唤醒,找到队列中唯一的元素,并获取它。 thread2稍后唤醒,按queue.isEmpty检查队列中是否有任何元素,然后等待 再一次 问题是obj可能会调用所有等待的线程。notifyAll,这些唤醒的线程将以不确定的顺序进入同步代码块,并操作共享数据。因此,有必要检查while循环中的条件

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

 synchronized (obj) {
     while (queue.isEmpty())
         obj.wait();
     ... // Perform action appropriate to condition
     queue.take();
 }
thread3将元素放入此队列后,调用obj.notifyAll,这将调用thread1和thread2 up:

thread1首先唤醒,找到队列中唯一的元素,并获取它。 thread2稍后唤醒,按queue.isEmpty检查队列中是否有任何元素,然后等待 再一次 while循环头中的条件可以是以布尔形式解析的任何表达式

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

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

然后,while循环的负责人将检查当前时间是否不是中午12点。如果这是真的,该方法就无法开始它的实际工作。但为了防止阻塞资源,它将允许其他线程通过调用obj.wait来使用obj。 当我们到达中午12点时,while循环的条件将为false,线程存在while循环并执行其余代码。

while循环头中的条件可以是任何解析为布尔值的表达式

在您的示例中,while循环应该暂停实方法的执行,直到某个特定的co 这是真的

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

然后,while循环的负责人将检查当前时间是否不是中午12点。如果这是真的,该方法就无法开始它的实际工作。但为了防止阻塞资源,它将允许其他线程通过调用obj.wait来使用obj。 当我们到达中午12点时,while循环的条件将为false,线程存在while循环并执行其余代码

我无法理解while循环中的条件意味着什么

从字面上看,它意味着你等待发生的条件的逻辑倒转

当循环中的条件被其他线程修改时,线程t检查该条件之前是否有机会

假设1是,当另一个线程持有obj上的锁时,构成条件的变量仅由另一个线程更新

因此,在while循环之后的某个时刻,上面代码中的线程知道该条件现在为true,并且在释放锁之前,不会有任何其他更改

现在。。。明显地如果其他线程在不持有锁的情况下更改构成条件的变量,那么您担心的事情可能会发生。但这是一个有缺陷的程序。您拥有由不同线程更新的共享变量,但没有足够的同步

1-线程在调用obj.notify或obj.notifyAll时必须持有该锁。如果没有,您将得到一个异常。但是,如果变量在单独的同步块中更新到notify调用,那么受保护的条件也会起作用。这只会让代码更难理解

2-在此上下文中,将变量声明为volatile对于保护条件的正确行为是不够的

我无法理解while循环中的条件意味着什么

从字面上看,它意味着你等待发生的条件的逻辑倒转

当循环中的条件被其他线程修改时,线程t检查该条件之前是否有机会

假设1是,当另一个线程持有obj上的锁时,构成条件的变量仅由另一个线程更新

因此,在while循环之后的某个时刻,上面代码中的线程知道该条件现在为true,并且在释放锁之前,不会有任何其他更改

现在。。。明显地如果其他线程在不持有锁的情况下更改构成条件的变量,那么您担心的事情可能会发生。但这是一个有缺陷的程序。您拥有由不同线程更新的共享变量,但没有足够的同步

1-线程在调用obj.notify或obj.notifyAll时必须持有该锁。如果没有,您将得到一个异常。但是,如果变量在单独的同步块中更新到notify调用,那么受保护的条件也会起作用。这只会让代码更难理解


2-在此上下文中,将变量声明为volatile对于保护条件的正确行为是不够的。

谢谢您的回答。我想了解一下,一般来说,我们在什么条件下必须循环等待?你能分享一些信息吗?他们是。。。大体上不管你在等什么。也许它在等待一个可用的值,等待计数器达到零,等待队列或缓冲区中的可用空间……感谢您的回答。我想了解一下,一般来说,我们在什么条件下必须循环等待?你能分享一些信息吗?他们是。。。大体上不管你在等什么。可能它正在等待一个值可用,等待计数器达到零,等待队列或缓冲区中的可用空间。。。