【发布时间】:2015-02-27 14:51:34
【问题描述】:
我正在尝试熟悉 wait() 和 notify() 方法,并且我编写了一个简单的类,其作用类似于一个简单的生产者-消费者练习的监视器,其中有 N 个生产者和 N 个消费者。无论如何,按照练习中的要求,显示器只能存储 3 个项目。所以生产者必须等待;相反,如果监视器中有 0 个项目,则消费者必须等待。
public class Monitor {
private List<Integer> items;
private int capacity;
private Object waitProducer;
private Object waitConsumer;
private int counter;
public Monitor() {
this.items = new ArrayList<Integer>();
this.capacity = 3;
this.waitProducer = new Object();
this.waitConsumer = new Object();
this.counter = 0;
}
public void produce() throws InterruptedException {
synchronized (this) {
if (this.items.size() == this.capacity) {
synchronized (this.waitProducer) {
System.out.println("Producer " + Thread.currentThread().getId() + " aspetta");
this.waitProducer.wait(); /***/
}
}
counter++;
System.out.println("Thread " + Thread.currentThread().getId()
+ " produces object " + counter);
this.items.add(counter);
synchronized (this.waitConsumer) {
this.waitConsumer.notify();
}
}
}
public void consume() throws InterruptedException {
synchronized (this) {
if (this.items.size() == 0) {
synchronized (this.waitConsumer) {
this.waitConsumer.wait(); /***/
}
}
System.out.println("Thread " + Thread.currentThread().getId()
+ " consume object " + this.items.get(0));
this.items.remove(0);
synchronized (this.waitProducer) {
this.waitProducer.notify();
}
}
}
}
我认为 /***/ 存在问题:事实上,当调用 wait() 方法时,线程释放了 waitProducer(或 waitConsumer)上的锁,但它没有在 Monitor 对象上。这就是为什么当(第一个消费者的)第一个生产者调用 wait() 时,Monitor 对象不再可获取。显然,对 Monitor 对象的访问必须是互斥的,以便正确更新列表和计数器。那么,正确的方法是什么?谢谢
【问题讨论】:
-
为什么外面的
synchronized(this)在那里?在this.waitProducer.wait()等待时,没有其他线程可以进入。 -
@LoryLory 在谷歌上快速搜索 volatile 与同步
-
@LoryLory 你应该考虑
java.util.concurrent.Lock并使用多个Conditions。它会更容易做你想做的事。 -
@nafas 同样,它们不是彼此的替代品。他们提供非常不同的服务。同步可防止竞争条件并确保变量或数据结构内的数据的稳定性。这可以被认为是执行控制。易失性与内存可见性有关,它可以防止数据被缓存,因此在访问时它始终是最新的。然而,这并不能防止潜在的竞争条件。
-
@LoryLory 这是Condition interface的JavaDoc
标签: java multithreading wait synchronized notify