2

假设 d 是我们用来调用等待的对象。当线程调用 d.wait 时,它必须拥有 d 的内在锁——否则会引发错误。在同步方法中调用 wait 是获取内在锁的一种简单方法。

那么这是否意味着两个线程不能同时调用 wait() ?这里的内在锁是什么意思[提到它作为监视器]?但是如何实现监控以实现互斥呢?

一旦线程调用等待它会永远持有对象吗?如果是这样,其他线程如何使用该锁进行 notifyAll()?

如果我们需要在 notifyall 期间获取对象,那么为什么要通知所有等待的线程?它不应该单独通知等待该对象的线程吗?

任何解释的代码表示赞赏。

4

4 回答 4

3

那么这是否意味着两个线程不能同时调用 wait() ?

纠正两个线程不能同时调用wait()。但是,一旦一个线程处于 wait() 中,另一个线程可以获取相同的锁并在不久之后进入 wait() 状态。您可以在同一个对象上等待任意数量的线程,但只有一个真正持有锁。

这里的内在锁是什么意思[提到它作为监视器]?但是如何实现监控以实现互斥呢?

持有对象时只能运行一个线程。其他线程可能会阻塞尝试获取锁,并且可能会等待()更多线程。

一旦线程调用等待它会永远持有对象吗?

相反,它放弃它或另一个线程几乎可以立即获取它。

如果是这样,其他线程如何使用该锁进行 notifyAll()?

如果您在对象上调用 notifyAll(),则依次唤醒所有 wait() 线程。这些线程一次只能获取一个锁,并且会尽快重新获取锁。

如果我们需要在 notifyall 期间获取对象,那么为什么要通知所有等待的线程?

这就是 notifyAll 所做的,它被认为比使用 notify 更安全,后者会唤醒一个随机的,因为它不太容易出现编码错误。

它不应该单独通知等待该对象的线程吗?

这就是它的作用。


你应该注意到;

  • 在您 notify()/notifyAll() 之前,您应该执行状态更改。您还应该在检查状态更改的循环内等待()。您需要这样做,因为 a) wait() 可能会错过 notify(),b) 它可能会虚假唤醒 c) 另一个线程可能会抓取您所做的任何事情,并且可能需要再次等待。
  • 在过去的 9 年中,高级并发类的使用越来越多。使用这些类意味着您不需要直接使用线程、队列、wait() 和 notify()。
于 2013-07-30T18:32:17.543 回答
1

在同步方法中调用 wait 是获取内在锁的一种简单方法。

Wait 不提供对象上的锁,而是使线程在其他线程调用 notify 时等待侦听锁释放。线程进入受保护的//同步块时获得锁。如果可用,同步块/方法允许获取锁,否则线程无法进入那些代码块。

于 2013-07-30T18:18:35.160 回答
0

当您调用 时wait(),您会释放该对象上的内在锁,直到另一个线程调用notify()notifyAll()对其进行调用。此时,JVM 将唤醒其中一个等待的线程,并自动重新获取该对象上的锁。

所以要回答你的问题,是的,多个线程可以wait()在同一个对象上。

于 2013-07-30T18:30:23.930 回答
0

根据 javadoc,锁不会永远持有:

线程释放此监视器的所有权并等待,直到另一个线程通过调用 notify 方法或 notifyAll 方法通知在此对象的监视器上等待的线程唤醒。然后线程等待直到它可以重新获得监视器的所有权并恢复执行。

于 2013-07-30T18:20:56.407 回答