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

Java并发、等待和通知之间的连接、死锁,java,multithreading,concurrency,synchronized,Java,Multithreading,Concurrency,Synchronized,我不熟悉Java中的基本并发。 据我所知,如果一个同步块中只有一个线程处于活动状态,而另一个线程正在等待,那么一个同步块中就可能有多个线程。 当我在学习一本关于java的书时,我试图解决一个关于读写器问题的练习,3个读写器应该读数字,3个写写器如何打印出从0到4的数字,然后结束。给出了main类、writer类和reader类(见下文)。 我的书给出的官方解决方案是(“Erzeuger”应该是“作家”,“Verbraucher”应该是“读者”,“Wert”是设定的值): 但是,如果一开始所有读

我不熟悉Java中的基本并发。 据我所知,如果一个同步块中只有一个线程处于活动状态,而另一个线程正在等待,那么一个同步块中就可能有多个线程。 当我在学习一本关于java的书时,我试图解决一个关于读写器问题的练习,3个读写器应该读数字,3个写写器如何打印出从0到4的数字,然后结束。给出了main类、writer类和reader类(见下文)。 我的书给出的官方解决方案是(“Erzeuger”应该是“作家”,“Verbraucher”应该是“读者”,“Wert”是设定的值):

但是,如果一开始所有读卡器都进入get方法的等待状态,因为还没有可用的值,“verfuegbar”标志为false,那么我不会陷入死锁。 然后,一个写入程序可以创建一个值,一个读卡器可以被notify唤醒,然后所有三个写入程序都可以进入put方法的等待状态,然后读卡器可以读取该值,然后另一个读卡器可以被唤醒,因此它们都进入等待方法,这是一个死锁

我在这里遗漏了什么,还是这本书的解决方案错了?
提前谢谢

建议您在继续使用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();
}
这里体现了两条规则:

  • 除非持有锁,否则任何人都不会更改显式条件的状态,并且

  • 如果消费者在获取锁时条件已为真,则消费者不会等待()


  • 如果您遵循这种模式,您将永远不会丢失通知。如果生产者碰巧首先获得了锁,那么消费者将保证在获得锁后不会调用
    lock.wait()
    。如果消费者碰巧首先获得了锁,则可以保证它安全地处于
    wait()
    调用中,并在生产者发送通知之前准备好接收通知。

    最好在您的问题中格式化并发布您的代码。很可能这本书没有错,你误解了一些事情。阅读数百个与并发、同步和等待/通知相关的其他问题,直到您理解(或者将您的问题修改为比“我不理解这本书,请向我解释”更合适的问题)。