【问题标题】:Confused on producer-consumer solution (synchronization clarification)对生产者-消费者解决方案感到困惑(同步澄清)
【发布时间】:2012-01-18 00:41:46
【问题描述】:

我一直在学习 Java 中的并发性,但遇到了生产者-消费者问题。这显然是标准的,我在很多地方都看到了几乎相同的答案。

public synchronized void put(int num){
    while (!empty) {
        try{
            wait(); }
        catch {}
    }

    buffer=num;
    empty=false;
    notify();
}

public synchronized int take(){
    while (empty) {
        try{
            wait(); }
        catch {}
    }

    empty=true;
    notify();
    return buffer;
}

我对同步的理解是它使用对象范围的锁,这意味着线程不能同时在 put 和 take 中。但是,两种方法都等待另一种方法。这就是我感到困惑的地方:这似乎造成了僵局。如果线程 A 进入 while empty=false,它将等待。但是,线程 B 不能进入 take,因为它是同步的。因此 empty 将永远为 false,造成死锁。

然而,鉴于我基本上看过这个答案多少次,它似乎一定是正确的。我理解错了什么?

谢谢!

【问题讨论】:

    标签: java multithreading concurrency synchronized producer-consumer


    【解决方案1】:

    调用wait会释放进入方法时获取的锁。因此,如果 A 输入 put 并调用 wait,则锁被释放,然后 B 可以在 take 中继续。

    来自javadoc

    The current thread must own this object's monitor. The thread releases ownership 
    of this monitor and waits until another thread notifies threads waiting on this 
    object's monitor to wake up either through a call to the notify method or the 
    notifyAll method. The thread then waits until it can re-obtain ownership of the 
    monitor and resumes execution. 
    

    【讨论】:

    • 好的,这肯定有助于澄清事情。但是,如果 B 在 take 内部并调用 notify(),这会唤醒 A,但 A 没有锁定它当前在内部的方法(因为 B 在离开 take 之前还有一行)。那么 A 是重新进入睡眠状态还是在没有实际 wait() 的情况下等待?
    • @Akroy,在我引用的文本之后还有一句话:“线程然后等待,直到它可以重新获得监视器的所有权并恢复执行。”我已将其添加到帖子中。现在你有了我希望的全貌。
    • 我想是的,这越来越清楚了!最后澄清一下:所以,如果在原来的情况下,A 正在等待,那么另一个生产者 C 也进来并在 put 内等待,这将如何工作? B调用通知会唤醒A和C吗?或者它会是一个首先响应的竞争条件?非常感谢!
    • 不会出现生产者和消费者都会等待的情况,因为您的队列只有 1 个项目的容量(即,它要么是空的,要么是满的,不能同时发生)。跨度>
    • 但是,如果我有两个制作人在等待,是否只是不确定哪一个醒了?还是会产生一些问题?
    猜你喜欢
    • 2016-08-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-03-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多