【问题标题】:Java concurrency, connection between wait and notify, deadlocks [closed]Java并发,等待和通知之间的连接,死锁[关闭]
【发布时间】:2021-06-12 16:13:39
【问题描述】:

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

但是,如果一开始所有读者都进入 get 方法的等待状态,因为还没有可用的值并且“verfuegbar”标志为假,我会不会遇到死锁。 然后一个写者可以创建一个值,一个读者可以被通知唤醒,然后所有三个写者都可以进入 put 方法的等待状态,然后读者可以读取该值,然后另一个读者可以被唤醒起来,所以他们都落在了等待方法里面,这是一个死锁?

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

【问题讨论】:

  • 最好在您的问题中格式化和发布您的代码。 Please do not upload images of code/errors when asking a question.
  • 很可能这本书没有错,而您误解了一些事情。阅读与并发、同步和等待/通知相关的数百个其他问题,直到您理解为止(或修改您的问题,使其更适合“我不理解这本书,请给我解释一下”)。

标签: java multithreading concurrency synchronized


【解决方案1】:

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

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

消费者:

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()调用中安全,并在生产者发送通知之前准备好接收通知。

【讨论】:

    【解决方案2】:

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多