1114. 按顺序打印

1114. Print in Order

提问人:xyz xyz 提问时间:5/4/2023 更新时间:5/4/2023 访问量:32

问:

我正在解决 Leetcode 问题 1114。我使用的是 wait( ) 和 notify( ) 概念。使用 wait() 给出时间限制超过,但使用 notifyAll() 给出正确答案。

为什么使用 notify() 给出 TLE 并使用 notifyAll() 它工作正常?

class Foo {
    private boolean oneDone;
    private boolean twoDone;
    
    public Foo() {
        oneDone = false;
        twoDone = false;
    }

    public synchronized void first(Runnable printFirst) throws InterruptedException {
        printFirst.run();
        oneDone = true;
        //notify();
        notifyAll();
    }

    public synchronized void second(Runnable printSecond) throws InterruptedException {
        while (!oneDone) {
            wait();
        }
        printSecond.run();
        twoDone = true;
        //notify();
        notifyAll();
    }

    public synchronized void third(Runnable printThird) throws InterruptedException {
        while (!twoDone) {
            wait();
        }
        printThird.run();
    }
}

为什么 notify() 给出 TLE 而 notifyAll() 不给出 TLE ?

Java 并发 等待 通知

评论


答:

0赞 Feel free 5/4/2023 #1

唤醒在此对象的监视器上等待的所有线程。线程通过调用其中一个等待方法在对象的监视器上等待。在当前线程放弃对此对象的锁定之前,唤醒的线程将无法继续。notifyAll()

用于仅唤醒一个随机选择的线程,该线程正在等待对象,然后该线程开始执行。这个随机选择的线程将放弃锁,如果不是下一个线程,则返回等待状态,这可能导致死锁。notify()

在代码中使用可能会导致线程错过信号并返回到等待状态,如果等待线程未在超时期限内唤醒,则可能导致 TLE。notify()

使用唤醒所有等待的线程,消除丢失信号和潜在死锁的可能性,使代码正常运行。notifyAll()

评论

0赞 xyz xyz 5/4/2023
因此,如果我们有两个以上的线程,那么最好使用 notifyAll()。如果我们只有两个线程,那么我们可以使用 notify()。如果我错了,请纠正我??
0赞 Feel free 5/4/2023
在大多数情况下,使用 notifyAll() 而不是 notify() 更安全,无论涉及的线程数如何。即使只有两个线程,如果您使用 notify() 方法,一个线程也有可能错过信号并返回等待。所以我建议在大多数情况下使用 notifyAll()
0赞 Feel free 5/4/2023
更多信息在这里 -> stackoverflow.com/questions/37026/...
0赞 Feel free 5/4/2023
很乐意帮忙。不要忘记了解有关关闭/接受问题 stackoverflow.com/help/accepted-answer 的知识