我的问题纯粹是概念性的。并且仅是为了更深入地了解线程之间的通信。
在生产者消费者问题中,
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的链表不是线程安全的。
但是,您可以使用concurrent版本将此锁定抽象到数据结构本身中。
另一个后果:在此示例中,只有生产者,只有一个消费者,但并非总是如此。具有多个生产者和/或使用者的用例可能需要使用同步,即使对于线程安全的数据结构也是如此。