C#生产者/消费者模式

我有简单的一个生产者/两个消费者代码如下,但输出显示只有C2消耗。 我的代码中有任何错误吗?

 class Program { static void Main(string[] args) { Object lockObj = new object(); Queue queue = new Queue(); Producer p = new Producer(queue, lockObj); Consumer c1 = new Consumer(queue, lockObj, "c1"); Consumer c2 = new Consumer(queue, lockObj, "c2"); Thread t1 = new Thread(c1.consume); Thread t2 = new Thread(c2.consume); t1.Start(); t2.Start(); Thread t = new Thread(p.produce); t.Start(); Console.ReadLine(); } } public class Producer { Queue queue; Object lockObject; static int seq = 0; public Producer(Queue queue, Object lockObject) { this.queue = queue; this.lockObject = lockObject; } public void produce() { while( seq++ <15) //just testinng 15 items { lock (lockObject) { string item = "item" + seq; queue.Enqueue(item); Console.WriteLine("Producing {0}", item); if (queue.Count == 1) { // first Monitor.PulseAll(lockObject); } } } } } public class Consumer { Queue queue; Object lockObject; string name; public Consumer(Queue queue, Object lockObject, string name) { this.queue = queue; this.lockObject = lockObject; this.name = name; } public void consume() { string item; while (true) { lock (lockObject) { if (queue.Count == 0) { Monitor.Wait(lockObject); continue; } item = queue.Dequeue(); Console.WriteLine(" {0} Consuming {1}", name, item); } } } } 

输出是:

 Producing item1 c2 Consuming item1 Producing item2 c2 Consuming item2 Producing item3 c2 Consuming item3 Producing item4 c2 Consuming item4 Producing item5 c2 Consuming item5 Producing item6 c2 Consuming item6 Producing item7 c2 Consuming item7 Producing item8 c2 Consuming item8 Producing item9 c2 Consuming item9 Producing item10 c2 Consuming item10 Producing item11 c2 Consuming item11 Producing item12 c2 Consuming item12 Producing item13 c2 Consuming item13 Producing item14 c2 Consuming item14 Producing item15 c2 Consuming item15 

首先,我无法重现您的问题,这里两个线程都消耗了一些项目。 我想你的机器速度更快,但像gw建议的那样添加睡眠会解决这个问题。 我还建议您不要尝试同步生产者,我的意思是让它尽可能快地排队项目,并让消费者同步以查看谁处理每个项目。 我做了一个快速修改,似乎工作正常:

 static void Main() { Object lockObj = new object(); Queue queue = new Queue(); Producer p = new Producer(queue); Comsumer c1 = new Comsumer(queue, lockObj, "c1"); Comsumer c2 = new Comsumer(queue, lockObj, "c2"); Thread t1 = new Thread(c1.consume); Thread t2 = new Thread(c2.consume); t1.Start(); t2.Start(); Thread t = new Thread(p.produce); t.Start(); Console.ReadLine(); } } public class Producer { Queue queue; static int seq; public Producer(Queue queue) { this.queue = queue; } public void produce() { while (seq++ < 1000) //just testinng 15 items { string item = "item" + seq; queue.Enqueue(item); Console.WriteLine("Producing {0}", item); } } } public class Comsumer { Queue queue; Object lockObject; string name; public Comsumer(Queue queue, Object lockObject, string name) { this.queue = queue; this.lockObject = lockObject; this.name = name; } public void consume() { string item; while (true) { lock (lockObject) { if (queue.Count == 0) { continue; } item = queue.Dequeue(); Console.WriteLine(" {0} Comsuming {1}", name, item); } } } } 

您还可以添加睡眠以减慢消费者循环。

出于测试目的,请尝试在使用者代码中添加时间延迟。 情况可能是“消费”如此之快以至于一个消费者线程在其他消费者线程有机会之前清空队列。

(编辑)

我怀疑,添加一个

Thread.sleep代码(500);

在消费者线程内部(为了模拟正在进行的一些冗长的处理)导致两个线程被利用。

当队列计数等于1时,你的生产者只调用Monitor.PulseAll,因为生产者没有做任何实质内容,这意味着通过门的第一个消费线程将使第一个项目出列,第二个消费线程将看不到队列中的任何项目,因此点击Monitor.Wait,并且Pulse不会再次发生(可能直到除了最后一个项目之外的所有项目),以便第二个线程将无限期地等待。

添加了Thread.Sleep(500); 在Consumer.comsume

然后我有以下,

c2 Comsuming item1 c1 Comsuming item2 c2 Comsuming item3 c1 Comsuming item4 c2 Comsuming item5 c1 Comsuming item6 c2 Comsuming item7 c1 Comsuming item8 …..添加Sleep后resule不确定。

我运行了你的代码并且c1的喷射进行消耗和喷射c2。 您可能只想从msdn检查此链接: 如何:同步生产者和消费者线程(C#编程指南)

我认为你的目的是让多个消费线程“并行”工作。 但是你的代码效率很低。 这两个消费线程基本上是按顺序工作的。 实际工作代码应放在锁外,这样两个消费者线程就可以真正并行运行。 如果您有多个核心,甚至在单个核心机器上,这将改善运行时间,具体取决于工作的属性。 否则,实际上没有必要拥有多个消费线程,因为无论如何,所有消耗线程都是按顺序运行的。