Java API中的wait的同步解释

waitpublic final voidwait(long timeout) throws

导致当前的线程等待,直到其他线程调用此对象的notify()方法或notifyAll()方法,或者超过指定的时间量。

当前的线程必须拥有此对象监视器。

此方法导致当前线程(称之为T)将其自身放置在对象的等待集中,然后放弃此对象上的所有同步要求。出于线程调度目的,线程
T被禁用,且处于休眠状态,直到发生以下四种情况之一:

  • 其他某个线程调用此对象的notify方法,并且线程T碰巧被任选为被唤醒的线程。
  • 其他某个线程调用此对象的notifyAll方法。
  • 其他某个线程线程
    T
  • 已经到达指定的实际时间。但是,如果timeout为零,则不考虑实际时间,该线程将一直等待,直到获得通知。
然后,从对象的等待集中删除线程
T,并重新进行线程调度。然后,该线程以常规方式与其他线程竞争,以获得在该对象上同步的权利;一旦获得对该对象的控制权,该对象上的所有其同步声明都将被还原到以前的状态
- 这就是调用wait方法时的情况。然后,线程Twait方法的调用中返回。所以,从
wait方法返回时,该对象和线程T的同步状态与调用wait方法时的情况完全相同。

在没有被通知、中断或超时的情况下,线程还可以唤醒一个所谓的虚假唤醒(spurious
wakeup)。虽然这种情况在实践中很少发生,但是应用程序必须通过以下方式防止其发生,即对应该导致该线程被提醒的条件进行测试,如果不满足该条件,则继续等待。换句话说,等待应总是发生在循环中,如下面的示例:

synchronized (obj) { while (<condition does not hold>) obj.wait(timeout); ... // Perform action appropriate to condition }(有关这一主题的更多信息,请参阅
Doug Lea 撰写的《Concurrent Programming in Java (Second Edition)》(Addison-Wesley,
2000) 中的第 3.2.3 节或 Joshua Bloch 撰写的《Effective Java Programming Language
Guide》(Addison-Wesley, 2001) 中的第 50 项。

如果当前线程在等待时被其他线程,则会抛出
InterruptedException。在按上述形式恢复此对象的锁定状态时才会抛出此异常。

注意,由于wait
方法将当前的线程放入了对象的等待集中,所以它只能解除此对象的锁定;可以同步当前线程的任何其他对象在线程等待时仍处于锁定状态。

此方法只应由作为此对象监视器的所有者的线程来调用。请参阅 notify 方法,了解线程能够成为监视器所有者的方法的描述。

参数:
timeout - 要等待的最长时间(以毫秒为单位)。
抛出:

- 如果超时值为负。

- 如果当前的线程不是此对象监视器的所有者。

- 如果在当前线程等待通知之前或者正在等待通知时,另一个线程中断了当前线程。在抛出此异常时,当前线程的中断状态被清除。
另请参见:notif(),notiryAll()

posted on 2012-06-19 15:37  20:49  阅读(636)  评论(0编辑  收藏  举报

导航