消费生产者问题-是否总是需要同步?

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

我的问题纯粹是概念性的。并且仅是为了更深入地了解线程之间的通信。

在生产者消费者问题中,

  • 有一个生产者线程和一个消费者线程。
  • 生产者线程调用方法producer,而消费者线程调用方法消耗。

The example code is taken from here

package ProducerConsumer;
import java.util.LinkedList;
import java.util.Queue;
public class ClassicProducerConsumerExample {
    public static void main(String[] args) throws InterruptedException {
        Buffer buffer = new Buffer(2);
        Thread producerThread = new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    buffer.produce();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });
        Thread consumerThread = new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    buffer.consume();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });
        producerThread.start();
        consumerThread.start();
        producerThread.join();
        consumerThread.join();
    }
    static class Buffer {
        private Queue<Integer> list;
        private int size;
        public Buffer(int size) {
            this.list = new LinkedList<>();
            this.size = size;
        }
        public void produce() throws InterruptedException {
            int value = 0;
            while (true) {
                synchronized (this) {
                    while (list.size() >= size) {
                        // wait for the consumer
                        wait();
                    }
                    list.add(value);
                    System.out.println("Produced " + value);
                    value++;
                    // notify the consumer
                    notify();
                    Thread.sleep(1000);
                }
            }
        }
        public void consume() throws InterruptedException {
            while (true) {
                synchronized (this) {
                    while (list.size() == 0) {
                        // wait for the producer
                        wait();
                    }
                    int value = list.poll();
                    System.out.println("Consume " + value);
                    // notify the producer
                    notify();
                    Thread.sleep(1000);
                }
            }
        }
    }
}

我已经读到,wait and notify应该在同步块内,以避免出现竞争状况。

我不明白为什么当两个线程都调用不同的方法时,为什么要在同步块中包含wait()和notify()。使用者线程将不会调用produce(),因此,如果我不将农产品的wait调用包含在synchronized关键字中,则它应该仍然表现相同,因为producer()仅由生产者线程调用。是吗?

java multithreading wait synchronized producer-consumer
1个回答
1
投票

两个线程都将要从中添加/删除的缓冲区是一个链表。 Java的链表不是线程安全的。

但是,您可以使用concurrent版本将此锁定抽象到数据结构本身中。


另一个后果:在此示例中,只有生产者,只有一个消费者,但并非总是如此。具有多个生产者和/或使用者的用例可能需要使用同步,即使对于线程安全的数据结构也是如此。

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