public class ShareResource {
private int n = 0;
public synchronized void p() throws InterruptedException {
while (n > 0) {
wait();
}
n++;
}
public synchronized void r() {
n = 0;
notifyAll();
}
}
如果我使用此资源启动了两个线程,并且它们都在wait()处,并且我在资源中调用了方法r(),这会唤醒两个线程而不检查条件吗? 是否会在两个线程中读取代码直到方法结束?在“相同”时间?
答案 0 :(得分:1)
是否将在两个线程中读取代码直到方法结束?在同一时间?
不,不。 notifyAll()
的工作方式是每个对象最终都从wait()
醒来后才执行它们的代码。但是,一次只能执行一个线程。因此,一个线程通过调用r()
退出循环后,它会增加计数器的数量,因此不会释放另一个线程。因此,只有一个线程执行到最后-不在两个线程中执行。
如果我使用此资源启动了两个线程,并且它们都在wait()处,并且我在资源中调用了方法r(),这会唤醒两个线程而不检查条件吗?
我假设您的意思是当您表示“不检查条件”时退出while
循环。如上所述,两个线程都不是这种情况。
TL; DR:notifyAll()
一次只允许一个线程执行,但是所有这些线程最终都将最终执行。
答案 1 :(得分:1)
两个等待线程都收到通知。两个等待线程都在循环内唤醒。两者都必须检查条件才能退出循环。但是,其中一个等待线程将首先进入,然后将另一线程关上。
当等待线程被通知时,它仍处于wait方法中,直到获得锁,它才能离开wait方法。 (请记住,等待是在同步方法内部,并且线程在等待开始时就放弃了对ShareResource对象的锁定。)当然,一次只有一个线程可以获取该锁定。
在两个通知线程中,第一个获得锁的线程将离开wait方法,然后检查循环条件。它发现n为0,可以退出循环。然后线程递增n。所有这些都是在持有锁的情况下发生的,因此没有其他线程可以干涉。
一直以来,第二个线程已被阻塞;它被与第一个线程相同的通知唤醒,但是无法获取锁定。一旦第一个线程退出了p方法并释放了锁,第二个线程就可以获取该锁并退出wait方法。此时,它检查while循环条件,由于第一个线程,发现n大于0,然后再次输入wait方法,并返回到它开始的地方。
请注意,notifyAll通常很浪费,因为唤醒了多个线程,但是只有一个线程可以取得进展。