3

我需要知道 wait() 和 notify() 究竟是如何工作的?我无法通过使用 wait() 和 notify() 来实现它的工作。相反,如果我使用 while() 循环等待,它可以正常工作。怎么会这样?为什么我不能简单地使用 wait() 和 notify() ?

4

3 回答 3

4

wait() 和 notify() 在同步块中使用,同时使用线程在中断的地方暂停和恢复。

Wait 会立即释放锁,而 Nofity 只有在遇到结束括号时才会离开锁。

您还可以参考此示例示例:

public class MyThread implements Runnable {

    public synchronized void waitTest() {
        System.out.println("Before Wait");
        wait();
        System.out.println("After Wait");
    }

    public synchronized void notifyTest() {
        System.out.println("Before Notify");
        notify();
        System.out.println("After Notify");
    }
}


public class Test {

    public static  void main(String[] args) {
        Thread t = new Thread(new MyThread());
        t.start();    
    }
}
于 2013-07-02T07:04:02.717 回答
4

你读过等待通知函数的文档吗?

无论如何,为了实现等待通知机制的最佳方式,请使用类似这样的东西(基于此网站):

public class WaitNotifier {
    private final Object monitoredObject = new Object();
    private boolean wasSignalled = false;

    /**
     * waits till another thread has called doNotify (or if this thread was interrupted), or don't if was already
     * notified before
     */
    public void doWait() {
        synchronized (monitoredObject) {
            while (!wasSignalled) {
                try {
                    monitoredObject.wait();
                } catch (final InterruptedException e) {
                    break;
                }
            }
            wasSignalled = false;
        }
    }

    /**
     * notifies the waiting thread . will notify it even if it's not waiting yet
     */
    public void doNotify() {
        synchronized (monitoredObject) {
            wasSignalled = true;
            monitoredObject.notify();
        }
    }

}

请注意,此类的每个实例只能使用一次,因此如果您需要多次使用它,您可能需要更改它。

于 2013-07-02T07:08:59.630 回答
0

我想您是在问为什么它可以与 while 循环一起使用而没有. 答案是当你的程序调用wait()时,操作系统会挂起你的线程并激活(启动)另一个,并且会发生所谓的上下文切换。当操作系统挂起一个线程时,它需要保存一些“元数据”关于您的线程以便以后能够恢复该线程,PC寄存器将回答您的问题。基本上PC(程序计数器)是指向线程应该或将要执行的下一条指令的指针,在恢复后线程使用它来了解操作系统暂停他时它将执行哪条指令,并继续执行该指令(在这种情况下,如果您想通过Java程序查看它,下一条指令将是之后的下一行调用wait() )。如“ Java 并发实践”中所写

Every call to wait is implicitly associated with a specific condition predicate. When calling wait regarding a particular
condition predicate, the caller must already hold the lock associated with the condition queue, and that lock must also
guard the state variables from which the condition predicate is composed.

因为你的线程在返回到它被挂起的方法后因为某些条件没有满足(应该是)而等待,所以它需要重新检查该条件以查看它是否满足。如果条件满足,它将不再等待,如果没有遇到它会再次调用wait()(因为它在 while 循环中)。这里要知道的重要一点是

  1. PC(程序计数器)概念和
  2. 事实上,在您的方法上调用wait()的线程不会退出该方法 -> 等待 -> 再次恢复 -> 再次调用该方法,而是等待 -> 再次恢复 -> 从该点继续(指令/line) 被挂起的地方(称为 wait())
于 2020-07-12T02:57:34.723 回答