Java notify() 在 wait() 之前运行?

标签 java multithreading synchronized

public class ThreadA {
    public static void main(String[] args){
        ThreadB b = new ThreadB();
        b.start();

        synchronized(b){
            try{
                System.out.println("Waiting for b to complete...");
                b.wait();
            }catch(InterruptedException e){
                e.printStackTrace();
            }

            System.out.println("Total is: " + b.total);
        }
    }
}

class ThreadB extends Thread{
    int total;
    @Override
    public void run(){
        synchronized(this){
            for(int i=0; i<100 ; i++){
                total += i;
            }
            notify();
        }
    }
}

如上例,如果wait()先阻塞enter,ThreadB中后续的notify()会告诉Main Thread继续。

但是我们不能保证wait()会在notify()之前执行,如果ThreadB先进入block呢? Notify() 将在 wait() 之前执行,因此 wait() 将永远卡在那里(因为不再有 notify() 告诉它继续)?处理此问题的正确方法通常是什么?

最佳答案

你应该几乎总是有一个谓词和等待/通知。也就是说,你需要一个条件 您可以检查的内容,例如变量变为真、队列变为空/满等。只是盲目地等待某人调用 .notify() 的用例很少。

所以,以下是不正确的,因为你说的原因,另一个线程可以在 ThreadA 调用 .wait() 之前调用 .notify()

public class ThreadA {
    public static Object latch = new Object();
    public static void main(String[] args) {
        ThreadB b = new ThreadB();
        b.start();
        synchronized(latch ) {
            latch.wait(); //wait for B to finish a calculation
        }
        System.out.println("Total is: " + b.total);

    }
}

class ThreadB extends Thread {
    int total;

    @Override
    public void run() {
        for (int i = 0; i < 100; i++) {
            total += i;
        }
       synchronized(ThreadA.latch) {
           ThreadA.latch.notify();
       }
    }
}

你需要做这样的事情:

 public class ThreadA {
    public static Object latch = new Object();
    public static boolean done = false;
    public static void main(String[] args) {
        ThreadB b = new ThreadB();
        b.start();
        synchronized(latch ) {
            while (!done) {   //wait for B to indicate it is finished.
                latch.wait(); 
            }
        }
        System.out.println("Total is: " + b.total);

    }
}

class ThreadB extends Thread {
    int total;

    @Override
    public void run() {
        for (int i = 0; i < 100; i++) {
            total += i;
        }
       synchronized(ThreadA.latch) {
           ThreadA.done = true;         
           ThreadA.latch.notify();
       }
    }
}

请注意,在上面,done 变量受同步块(synchronized block)保护,.wait() 将自动释放/重新获取该锁。所以没有竞争条件,如果在我们到达 .wait() 调用之前调用了 .notify(),ThreadA 会发现,因为 done 将是 true 并且根本不进入 .wait() 调用。

对于像这段代码这样的简单情况,您可以等待 ThreadB 结束,可以使用 b.join();

关于Java notify() 在 wait() 之前运行?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19537636/

相关文章:

.net - 为什么 .NET Framework 2.0 上缺少 AutoresetEvent.WaitOne 重载

c# - 为什么对级联 ManualResetEvent 的多次等待会使执行时间增加三倍?

Java 将应用程序 move 到启动文件夹

java - Jersey .server.model.ModelValidationException

java - Dart VM服务客户端

java - 我应该始终在 Java 类中使用 getter/setter 方法,还是有时可以使用公共(public)属性?

Python 线程 'While' 不正常

java - 在同步方法中使用wait()和notify()

java - 如果两个线程使用不同的监视器,它们是否可以在同一个对象上执行相同的同步代码块?

java - Java 中的同步 - Vector 与 ArrayList