Java 并发,等待和通知之间的连接,死锁

Java concurrency, connection between wait and notify, deadlocks

我是 Java 中基本并发的新手。 据我了解,如果只有其中一个处于活动状态而其他线程正在等待,则可以在一个同步块中有多个线程。 当我学习一本关于 java 的书时,我试图解决一个关于 reader-writer-problem 的练习,其中 3readers 应该读取数字,而 3作者如何打印出 0 到 4 的数字然后结束。主要的class、作者class和readerclass(见下文)都给出了。 我的书给出的官方解决方案是这样的(“Erzeuger”应该是“writer”,“Verbraucher”应该是“reader”,“Wert”是设置的值): main class value class writer class reader class

但是如果一开始所有 reader 都进入 get 方法的等待状态,我会不会 运行 陷入死锁,因为还没有可用的值和“verfuegbar”标志是假的。 然后一个 writers 可以创建一个值,一个 reader 可以被 notify 唤醒,然后所有三个 writer 可以进入 put 方法的等待状态,然后 reader 可以读取值,那么另一个 reader 可能会被唤醒,所以它们都落在等待方法中,这是一个死锁?

我在这里遗漏了什么,或者这本书的解决方案有误? 提前致谢!

建议您在继续 Java 并发之前对软件系统有一般的工作概念。一旦您了解了信号量、互斥锁等的工作原理、死锁条件的概念、避免和预防等,您将对解决问题有更深入的了解。

我建议您阅读 William Stalling 的操作系统:设计与原理的第 6 章。

您描述的“死锁”有另一个名称:“丢失通知”。

为了正确使用 wait/notify,您需要一个明确的、可测试的条件,并且您需要遵循以下模式:

消费者:

synchronized (lock) {
    while (condition_is_not_true()) {
        lock.wait();
    }
    do_something_that_requires_condition_to_be_true();
    maybe_make_it_false_again_maybe_not_thats_up_to_you();
}

制作人:

synchronized (lock) {
    make_the_condition_true();
    lock.notify();
}

这里体现了两条规则:

  1. 除非持有锁,否则没有人会更改显式条件的状态,并且

  2. 消费者在获取锁时不会wait()如果条件已经为真

如果您遵循该模式,您将永远不会丢失通知。如果生产者刚好先拿到了锁,那么保证消费者一旦拿到锁就不会调用lock.wait()。如果消费者碰巧先获得了锁,那么它可以保证在 wait() 调用中安全,并准备好在生产者发送通知之前接收通知。