为了账号安全,请及时绑定邮箱和手机立即绑定

C#生产者/消费者

C#生产者/消费者

交互式爱情 2019-09-20 17:28:54
我最近遇到了生产者/消费者模式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);        }    }
查看完整描述

3 回答

?
月关宝盒

TA贡献1772条经验 获得超5个赞

代码比那个旧 - 我在.NET 2.0问世之前写了一段时间。该概念生产者/消费者队列的方式相比,虽然旧的:)

是的,就我所知,该代码是安全的 - 但它有一些不足之处:

  • 它不是通用的。现代版本肯定是通用的。

  • 它无法阻止队列。停止队列的一种简单方法(使所有消费者线程退出)是具有可以放入队列的“停止工作”令牌。然后,您可以添加与线程一样多的令牌。或者,您有一个单独的标志,表示您要停止。(这允许其他线程在完成队列中的所有当前工作之前停止。)

  • 如果工作量很小,一次只能完成一项工作可能不是最有效的工作。

诚实地说,代码背后的想法比代码本身更重要。


查看完整回答
反对 回复 2019-09-20
?
HUWWW

TA贡献1874条经验 获得超12个赞

如果您阅读评论,您将理解我的答案是错误的:)


您的代码中可能存在死锁。


想象一下以下情况,为清楚起见,我使用单线程方法,但应该很容易转换为多线程与睡眠:


// We create some actions...

object locker = new object();


Action action1 = () => {

    lock (locker)

    {

        System.Threading.Monitor.Wait(locker);

        Console.WriteLine("This is action1");

    }

};


Action action2 = () => {

    lock (locker)

    {

        System.Threading.Monitor.Wait(locker);

        Console.WriteLine("This is action2");

    }

};


// ... (stuff happens, etc.)


// Imagine both actions were running

// and there's 0 items in the queue


// And now the producer kicks in...

lock (locker)

{

    // This would add a job to the queue


    Console.WriteLine("Pulse now!");

    System.Threading.Monitor.Pulse(locker);

}


// ... (more stuff)

// and the actions finish now!


Console.WriteLine("Consume action!");

action1(); // Oops... they're locked...

action2();

如果这没有任何意义,请告诉我。


如果确认了这一点,那么您的问题的答案是“不,这不安全”;)我希望这会有所帮助。


查看完整回答
反对 回复 2019-09-20
  • 3 回答
  • 0 关注
  • 894 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信