2016-01-28 29 views
1

我有一个正常工作的生产者/消费者模式。 它有1个生产者和N个消费者。Producer消费者修改

现在我##标题##试图生产,然后同时消费,但仍然使用1生产者和N消费者线程。

所以基本上它应该像农产品() - >消费(),生产() - >消费(),生产() - >消耗()...

,但现在,我有多个消费者线程我希望他们在该条件等待(),所以如果之后产生() - >消耗()另一个消耗()发生的地方它等待。

所以说我有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(); 
      } 
     } 
    } 
} 

回答

1

你生产者/消费者安装可能会失败,我将讨论如何那是原因,但最初将解释为什么它的工作原理有点。生产者调用cond1.signalAll的原因是你如何设置生产者消费者沟通。计数器字段是生产者可以调用cond1.signalAll方法的原因。在这种情况下有可能的情况。

让我们开始假设生产者在任何消费者之前获得锁定。生产者然后会增加计数器,并使用cond.await调用将自己置于等待状态。这将导致制片人放弃其锁定并允许其中一名消费者获得锁定。获得锁定的消费者将看到计数大于零并继续减少计数器。然后它会调用cond.signalAll并使生产者收回锁。消费者然后释放锁并尝试重新获得锁。如果生产者重新获得锁定,它将执行上面提到的相同过程。如果消费者获得该锁,并且它会注意到该计数器为零,并通过调用cond1.await将自身置于等待状态。在这种情况下,制片人最终会获得锁定。

另一种情况是消费者在生产者获得锁之前获得锁。消费者会看到计数器为零,它将使用cond1.await将自己置于等待状态。它会放弃它的锁,另一个线程会获得锁。生产者然后可以获得锁定并且能够增加计数器并且使自己处于等待状态。然后消费者将获得锁定并能够在向生产者发信号之前消费柜台。

如果所有的消费者在生产者获得锁之前获得锁,会发生什么?在这种情况下,消费者将执行与上述相同的步骤。最终生产者将获得锁定并增加计数器。请注意,在这种情况下,制作人会在消费者醒来之前等待。这将导致你的制片人/消费者永远等待而不做任何工作。这是唯一会导致系统失败的情况。因此,建议您首先表明您在制作人处于等待状态之前已经为消费者工作。请注意,这种情况只有在您最初启动生产者/消费者线程时才会发生。通过启动所有消费者线程并等待一段时间,然后启动生产者,您可以轻松地重现此情况。这将产生上述情况。这实际上是一个你只需要考虑的边界情况。