Java:wait()、notify()和synchronized块

8
我了解到调用对象的wait()方法会释放对象监视器(如果存在)。
但是,我对在另一个线程上调用notify()时有一些问题:
  1. 如果另一个(第三个)线程同时拥有对象监视器,等待线程将在什么时候醒来?

  2. 如果第三个线程在此对象上调用wait(),等待线程是否会醒来?

  3. 是否可能确定线程是否正在等待通知特定对象(Java 1.4 / Java 5)

  4. 如果在finalize()方法中调用wait()会发生什么?

4个回答

3
当你从一个线程中调用wait()时,该线程停止执行并被添加到对象的等待集中。当你从另一个线程中调用notify()时,等待集中的一个随机线程会被唤醒,如果你调用notifyAll(),所有线程都将准备好执行。
当你调用notify()时,线程已经准备好运行,但这并不意味着它会立即执行,所以要小心。
  1. 它会随机唤醒等待集中的一个线程。
  2. 你不知道哪个线程会首先被唤醒,它不遵循任何顺序。
  3. Thread.getState()
  4. 你可能会产生死锁。

2
  1. 这就是为什么你有notify()notifyAll()方法。前者唤醒在对象上等待的一个线程,后者唤醒所有线程。如果在另一个线程中调用了wait(),则等待的线程不会被唤醒。

  2. 不可以。

  3. 只能调用thread.holdsLock(obj) 来查看线程是否持有特定对象的监视器锁。

  4. 不要在finalize方法中调用wait()


我接受第2到4点,但你对第1点的回答是错误的。我在谈论锁监视器(同步块)。 - MRalwasser

2
  1. notify会唤醒一个等待该监视器的线程。除非并且直到监视器被释放,否则没有等待的线程可以运行;必须在同步块中调用wait(),因此必须持有锁来继续运行该块。
  2. 没有保证。调用notifyAll给所有线程一个机会去唤醒。
  3. 不确定。您可以让线程在进入睡眠之前设置一个变量表示它正在等待...
  4. 这可能是个坏主意。你能想出一个必须要这样做的情况吗?

  1. "wait()必须在同步块中调用"是错误的。但它应该这样做。
  2. 是的,你说得对。
  3. 我认为Chris Denett在这里是正确的。Thread.holdsLock()听起来不错。
  4. 这更多是一个理论问题,以了解概念。
- MRalwasser
1
@MRalwasser:不同意,它必须这样。在这里看一下:https://dev59.com/hHE85IYBdhLWcg3wbS_1 - Marcus

0

2: 不一定。 notify()只会唤醒等待中的其中一个线程,可能是最开始等待的线程,也可能是第三个线程。

3: 使用thread.getState(),您可以找出线程是否正在等待对象,但我不确定您是否总能确切地找出是哪个对象。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接