在一个简单的Producer-Consumer实现中与同步,等待,notifyAll混淆

时间:2019-04-14 08:25:41

标签: java wait synchronized notify

在我的代码中,当生产者线程需要在生产者代码中等待时,我在while循环中尝试了两个类似的条件代码,以检查该框是否已满。但是输出却不同,我很困惑。

错误是当我使用一个名为'size'的变量来将box的size值保存在线程的运行代码中时。在某些情况下,该程序将像死亡一样被阻止。

生产者代码:

public class Producer implements Runnable{
    private final List<String> boxes;
    private final int MAX_SIZE = 5;
    public Producer(List<String> aboxes) {
        super();
        this.boxes = aboxes;
    }
    @Override
    public void run() {
        while (true) {
            synchronized (boxes) {
                try {
                    int size = boxes.size(); // OR int size = this.boxes.size();

                    // while(MAX_SIZE == this.boxes.size()) {      OK
                    // while(MAX_SIZE == boxes.size()) {           OK
                    while (MAX_SIZE == size) {                  // ERROR
                        boxes.wait();
                    }

                    Thread.sleep(500);
                    String product = "product :  " + UUID.randomUUID().toString();
                    boxes.add(product);

                    boxes.notifyAll();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }  
        }
    }
}

1 个答案:

答案 0 :(得分:4)

您当前情况下的while语句中的条件是静态的,即,当再次评估while循环时,两个变量的MAX_SIZE == size的值都不会改变。

notify上调用boxes并通知生产者线程时,将再次评估while循环。由于两个值都未更改,因此两个值都将为5,并且在评估循环时,其值将再次为5。因此,当条件为5==5时,会再次调用wait。即,一旦进入while循环,条件将始终为true,从而导致无限阻塞。

但是在条件MAX_SIZE == boxes.size()的情况下,boxes.size()的值是动态的,并且它将被更改,我想这是消费者的。假设,消费者从该列表中删除了一个元素,因此boxes.size()=4并在notify上调用boxes。因此,将通知生产者线程,并且producer中的条件变为5 == 4,导致条件为false并退出循环。因此,代码将按预期执行