我有一个正常工作的制作人/消费者模式。 它有1个制作人和N个消费者。
现在我##标题##想要尝试生成然后同时使用但仍然使用1个生产者和N个消费者线程。;
所以基本上它应该像produce() - > consume(),produce() - > consume(),produce() - > consume()......
但是现在我有多个消费者线程我希望它们在条件下等待(),所以如果在produce() - >之后消耗()另一个消耗()发生它等待的地方。
所以说我有1个制作人和4个消费者,它看起来像这样:
农产品() - >消耗() - >消耗()await->消耗()等待() - >。消耗()等待() - >产生() - 取代。 ..
问题:在生产者线程进入cond.await()之后,代码可以工作,但我不明白。为什么他仍然可以调用cond1.signalAll();? 顺序代码不应该在cond.await()停止吗?
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class Processor {
private Lock lock = new ReentrantLock();
private Condition cond = lock.newCondition();
private Condition cond1 = lock.newCondition();
private int Counter = 0;
public void produce() throws InterruptedException {
while(true) {
lock.lock();
try {
Counter++;
System.out.println("Increased by one");
Thread.sleep(1000);
cond.await();
cond1.signalAll();
} finally {
lock.unlock();
}
}
}
public void consume() throws InterruptedException{
while(true) {
lock.lock();
try {
while(Counter==0) {
cond1.await();
}
Counter--;
System.out.println("Decreased by one!");
Thread.sleep(1000);
cond.signalAll();
}
finally {
lock.unlock();
}
}
}
}
答案 0 :(得分:1)
您的生产者/消费者设置可能会失败,我将讨论这是什么原因,但最初会解释为什么它会有所作为。生产者确实调用cond1.signalAll的原因是您如何设置生产者消费者沟通。 Counter字段是生产者调用cond1.signalAll方法的原因。在这种情况下,有些情况是可能的。
让我们开始假设生产者在任何消费者做之前获得锁定。然后,生产者将递增计数器并使用cond.await调用将其置于等待状态。这将导致生产者放弃其锁定并允许其中一个消费者获得锁定。获得锁定的消费者将看到计数大于零并继续递减计数器。然后它将调用cond.signalAll并使生产者回收锁。然后消费者释放锁并试图重新获得锁定。如果生产者重新获得锁定,它将执行与上述相同的过程。相反,如果消费者获得锁定,它将注意到计数器为零并通过调用cond1.await将其置于等待状态。在这种情况下,生产者最终将获得锁定。
另一种情况是,如果消费者在生产者获得锁定之前获得锁定。消费者将看到计数器为零,并且它将使用cond1.await将自己置于等待状态。然后它将放弃其锁定,另一个线程将获得锁定。然后,生产者可以获得锁定并能够增加计数器并使其自身处于等待状态。然后,消费者将获得锁定并能够在向生产者发出信号之前使用计数器。
如果所有消费者在生产者获得锁定之前获得锁定会怎样?在这种情况下,消费者将执行与上述相同的步骤。最终,制作人将获得锁定并将增加计数器。请注意,在这种情况下,生产者将在信号之前等待消费者醒来。这将导致您的生产者/消费者在没有做任何工作的情况下永远等待。这是唯一会导致系统失败的情况。然后,建议您在放置生产者处于等待状态之前首先表明您已为消费者工作。请注意,这种情况只能在您最初启动生产者/消费者线程时发生。您可以通过启动所有使用者线程并等待一段时间然后启动生产者来轻松地重现此情况。这将产生上述情况。这实际上是您需要考虑的边界情况。