C#生产者/消费者

我最近遇到了生产者/消费者模式c#实现。它非常简单,(至少对我来说)非常优雅。


它似乎是在2006年左右设计的,所以我想知道这种实施是否

安全

- 仍然适用


代码如下(原始代码参考http://bytes.com/topic/net/answers/575276-producer-consumer#post2251375)


using System;  

using System.Collections;  

using System.Threading;


public class Test

{  

    static ProducerConsumer queue;


    static void Main()

    {

        queue = new ProducerConsumer();

        new Thread(new ThreadStart(ConsumerJob)).Start();


        Random rng = new Random(0);

        for (int i=0; i < 10; i++)

        {

            Console.WriteLine ("Producing {0}", i);

            queue.Produce(i);

            Thread.Sleep(rng.Next(1000));

        }

    }


    static void ConsumerJob()

    {

        // Make sure we get a different random seed from the

        // first thread

        Random rng = new Random(1);

        // We happen to know we've only got 10 

        // items to receive

        for (int i=0; i < 10; i++)

        {

            object o = queue.Consume();

            Console.WriteLine ("\t\t\t\tConsuming {0}", o);

            Thread.Sleep(rng.Next(1000));

        }

    }

}


public class ProducerConsumer

{

    readonly object listLock = new object();

    Queue queue = new Queue();


    public void Produce(object o)

    {

        lock (listLock)

        {

            queue.Enqueue(o);


            // We always need to pulse, even if the queue wasn't

            // empty before. Otherwise, if we add several items

            // in quick succession, we may only pulse once, waking

            // a single thread up, even if there are multiple threads

            // waiting for items.            

            Monitor.Pulse(listLock);

        }

    }

交互式爱情
浏览 892回答 3
3回答

月关宝盒

代码比那个旧 - 我在.NET 2.0问世之前写了一段时间。该概念生产者/消费者队列的方式相比,虽然旧的:)是的,就我所知,该代码是安全的 - 但它有一些不足之处:它不是通用的。现代版本肯定是通用的。它无法阻止队列。停止队列的一种简单方法(使所有消费者线程退出)是具有可以放入队列的“停止工作”令牌。然后,您可以添加与线程一样多的令牌。或者,您有一个单独的标志,表示您要停止。(这允许其他线程在完成队列中的所有当前工作之前停止。)如果工作量很小,一次只能完成一项工作可能不是最有效的工作。诚实地说,代码背后的想法比代码本身更重要。

HUWWW

如果您阅读评论,您将理解我的答案是错误的:)您的代码中可能存在死锁。想象一下以下情况,为清楚起见,我使用单线程方法,但应该很容易转换为多线程与睡眠:// We create some actions...object locker = new object();Action action1 = () => {&nbsp; &nbsp; lock (locker)&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; System.Threading.Monitor.Wait(locker);&nbsp; &nbsp; &nbsp; &nbsp; Console.WriteLine("This is action1");&nbsp; &nbsp; }};Action action2 = () => {&nbsp; &nbsp; lock (locker)&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; System.Threading.Monitor.Wait(locker);&nbsp; &nbsp; &nbsp; &nbsp; Console.WriteLine("This is action2");&nbsp; &nbsp; }};// ... (stuff happens, etc.)// Imagine both actions were running// and there's 0 items in the queue// And now the producer kicks in...lock (locker){&nbsp; &nbsp; // This would add a job to the queue&nbsp; &nbsp; Console.WriteLine("Pulse now!");&nbsp; &nbsp; System.Threading.Monitor.Pulse(locker);}// ... (more stuff)// and the actions finish now!Console.WriteLine("Consume action!");action1(); // Oops... they're locked...action2();如果这没有任何意义,请告诉我。如果确认了这一点,那么您的问题的答案是“不,这不安全”;)我希望这会有所帮助。
打开App,查看更多内容
随时随地看视频慕课网APP