线程无法访问 Java 中的可共享资源

Threads can't get the access to shareable resource in Java

我无法理解为什么 Consumers 中的共享列表总是空的,而 Provider 向其中添加值。 我有提供商:

class Provider extends Thread {
    List<Integer> products;
    Random rnd = new Random();

    public Provider(List<Integer> products) {
        this.products = products;
    }

    @Override
    public void run() {
        //Provider just generate random value and adds the value to the shared list
        for (int i = 0; i < 10; i++) {
            Integer product = rnd.nextInt(100);
            System.out.println("added value: "+product);
            products.add(product);
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

消费者:

class Consumer extends Thread {
    List<Integer> products;

    public Consumer(List<Integer> products) {
        this.products = products;
    }

    @Override
    public void run() {
        System.out.println("Consumer started");
        for (int i = 0; i < 5;) {
            //Consumer just removes elements from shared list five times
            if (!products.isEmpty()) {
                Integer product = products.remove(0);
                System.out.println("removed: "+product);
                i++;
            }
        }
        System.out.println("Consumer stopped");
    }
}

我主要有以下几点:

List<Integer> products = new ArrayList<>();
new Provider(products).start();
new Consumer(products).start();
new Consumer(products).start();

我假设每个消费者应该在提供者向其添加值后从可共享列表中读取五个值,但在消费者中,列表始终为空。为什么列表没有更新?

我得到以下结果:

Consumer started
Consumer started
added value: 13
removed: 13
removed: 13
added value: 28
added value: 53
added value: 32
added value: 85
added value: 23
added value: 60
added value: 10
added value: 15
added value: 85

提供者完成后,消费者正在工作,但由于条件原因无法删除任何项目。

请不要写同步。我知道线程应该同步对公共资源的访问。但这是研究示例,我的目标是让消费者读取并从列表中删除值。

我觉得第一条评论一针见血。如果没有 any 同步,则线程无法保证看到更新。尤其是像这样的紧密循环。

将同步添加到消费者对我有用。

class Consumer extends Thread {
    List<Integer> products;

    public Consumer(List<Integer> products) {
        this.products = products;
    }

    @Override
    public void run() {
        System.out.println("Consumer started");
        for (int i = 0; i < 5;) {
            //Consumer just removes elements from shared list five times
            synchronized(products){
                if (!products.isEmpty()) {
                    Integer product = products.remove(0);
                    System.out.println("removed: "+product);
                    i++;
                }
            }
        }
        System.out.println("Consumer stopped");
    }
}

当我在没有同步的情况下尝试这个时,消费者永远不会从列表中获取。