3

假设我有两个线程。Thread1 正在访问一个同步方法,同时 Thread2 正在访问同一对象的另一个同步方法。据我所知,Thread2 应该等到 Thread1 完成它的任务。我的问题是,Thread2 在对象的等待线程列表中吗?对我来说似乎是这样,但是 Thread2 没有调用 wait() 方法,那么作为逻辑结果,它不应该在对象的等待线程列表中。如果它不在对象的等待线程列表中,那么 Thread2 的状态是什么?

4

2 回答 2

2

当 Tread2 等待 Thread1 释放 Thread1 持有的内在锁时,它会被阻塞,直到内在锁变得可用(如 u 被执行线程 Thread1 释放)。所以,总而言之,Thread2 正在等待锁被释放,所以它可以获取它。

现在,当一个线程调用 时wait()它必须已经持有内部锁。调用wait()then会释放 lock,并将线程置于等待状态,等待来自notify()或 a的信号notifyAll()以继续执行。

所以,这两种情况是不同的,前者是关于执行被隐式阻塞,直到资源(锁)变得可用。而后者是关于显式释放一个已经持有的锁,然后等待一个信号,表明它是时候重新获取锁并继续了。

于 2013-04-30T23:54:55.377 回答
0

正如您正确指出的那样,这两种情况之间存在区别。

当一个线程试图运行一个synchronized块,但另一个线程持有监视器的锁时,传入的线程被阻塞,直到锁被释放并授予它。

对于要调用的线程wait(),它必须已经持有监视器的锁(这是一个相关的区别)。此外,调用wait()使线程等待(释放锁),通常直到它被其他线程通知。

在理想情况下,通常上述情况应该总是如此,但是,如 Java 文档中所述,可能会发生一种称为虚假唤醒的现象,使等待线程无缘无故地唤醒。这就是为什么等待条件应该包含在一个while语句中,而不是一个if. 例子:

synchronized (this) {
    while (x < 0) { wait(); }
}

代替:

synchronized (this) {
    if (x < 0) { wait(); }
}
于 2013-04-30T23:57:55.713 回答