在一个简单的Producer-Consumer工具中混淆了synchronized,wait,notifyAll

问题描述 投票:3回答:1

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

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

制片人代码:

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();
                }
            }  
        }
    }
}
java wait synchronized notify
1个回答
4
投票

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

当在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并退出循环。因此代码按预期执行

© www.soinside.com 2019 - 2024. All rights reserved.