繁体   English   中英

如何使用notify / wait()唤醒/挂起特定(组)线程?

[英]How can I wake/suspend a particular (Group of) Thread(s) with notify/wait()?

我想知道例如r.wait()有效吗? 使用此代码:

public class Buffer1<T> {
private T content;
private boolean empty;
private Object r = new Object();
private Object w = new Object();

public Buffer1() {
empty = true;    }

public Buffer1(T content) {
this.content = content;
empty = false;    }

public T take() throws InterruptedException {
synchronized (r) {
while (empty) {
r.wait();
}

synchronized (w) {
empty = true;
w.notify();
return content;
  }
 }
}

public void put(T o) throws InterruptedException {
synchronized(w) {
while (!empty) {
w.wait();
}

synchronized (r) {
empty = false;
r.notify();
content = o;
}

r.wait(),w.wait(),r.notify(),w.notify()如何工作? 它们如何与synchronized(r)/ synchronized(w)一起工作?

线程不会被挂起。 会发生什么是线程进入同步块或方法,获取锁(此处为r或w),如果线程调用等待其获取锁的对象,则线程被挂起,释放它称为等待的锁,并且被添加到该锁的等待集中。

这里有一个模式,周围有一个等待调用的循环。 调用该方法的线程必须一直等待,直到循环中的测试为假。 让线程从等待进入的状态称为条件。 在循环中调用wait方法主要是因为通知的线程没有锁的所有权,它需要在重新获取锁后测试当前状态。

你可以通过在该锁上调用notifyAll来唤醒锁的等待集中的所有线程。 在实践中,这不是最佳的,因为通常只有一个线程可以获得锁定并一次进行。 当争用同一个锁的线程可以等待不同的条件并且通知可能是针对与某些线程无关的状态时,会发生使用notifyAll。 如果使用notify,则只唤醒一个线程(在调度程序的一时兴起选择)。 如果线程正在等待的条件不是通知的条件,那么通知将丢失并且没有线程进行。 使用notifyAll,如果通知适用于任何线程,则其中一个线程可以取得进展。 即使以所有其他等待线程获得上下文切换并返回等待的代价,这也取代了替代方案。

在发布的代码中,意图似乎是通过为每个条件设置单独的锁定对象来避免使用notifyAll。 对象r有线程在等待它,直到缓冲区不为空,对象w有线程在等待它,直到缓冲区为空。 这样当调用notify时,它肯定会唤醒一个与通知相关的线程(只有等待put的线程才能被w.notify()唤醒)。

这段代码的问题在于put和take操作获得了两个锁,并且它们以相反的顺序获取它们。 这是造成僵局的一个非常好的方法。 使用synchronized关键字和内部锁定无法超时和退出,没有好的恢复方法。 一旦你有一个线程有r并想要w的情况,而另一个有w并且想要r,那么你就被卡住了。 每个持有锁的两个线程都无法进行,任何其他线程都无法获得任何锁定,导致每个线程都试图进入此缓冲区的方法,直到您终止JVM为止。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM