【问题标题】:Multiple consumers working with the same value多个消费者使用相同的值
【发布时间】:2016-10-31 19:44:01
【问题描述】:

我希望得到一些关于某种生产者/消费者场景的概念性建议。

假设我有一个“生产者”线程,它通常以相当周期性的方式创建一些整数或双精度值,但其间可能存在任意延迟。

现在有几个“消费者”线程,一旦值到达,所有线程都应该开始并行处理这个值。

这些“消费者”线程中的每一个都可能需要另外的时间来完成其任务。一旦“消费者”准备就绪,它就应该等待下一个产生的值。

但是,如果使用前一个值完成任务的时间过长,则消费者应立即继续使用任何到期的值(如果有)。我不需要队列,如果在消费者工作时有几个到达,则可能会跳过值。因此,唯一重要的是是否有新值,以及如果任何消费者准备好使用下一个值,那么哪个是最新的。

除了为每个“消费者”设置一个 AutoResetEvent/ManualResetEvent 之外,还有其他可行的方法吗?

具体方案应该是Unity3D,所以需要Mono2。

编辑:由于我对概念性建议感兴趣,因此很难提出一些源代码。我希望以下内容能稍微说明问题。

int data = 0;

producer = new Timer(20, OnTimer);
consumer1 = new Consumer(OnConsume1);
consumer2 = new Consumer(OnConsume2);

OnTimer()
{
        data = data + 20;
        TriggerConsumers();
}

OnConsume1()
{
        while (running)
        {
                WaitForData();
                // do something with data
                Thread.Sleep(10);
        }
}

OnConsume2()
{
        while (running)
        {
                WaitForData();
                // do something with data
                Thread.Sleep(30);
        }
}

有生产者,每 20 毫秒创建一个新值。然后有两个消费者(以后可能会更多)等待该值并对其进行处理。一个消费者需要 10 毫秒,另一个消费者需要 30 毫秒。 如果生产者/消费者同时开始,这应该会导致以下时间表:

20 数据 = 20 => OnConsume1,OnConsume2 运行数据 = 20 30 OnConsume1 将等待数据,OnConsume2 正在“工作” 40 数据 = 40 => OnConsume1 以数据 = 40 运行,OnConsume2 仍在“工作” 50 OnConsume1 将等待,OnConsume2 将运行 data = 40 60 数据 = 60 => OnConsume1 以数据 = 60 运行,OnConsume2 正在“工作” 70 OnConsume1 将等待,OnConsume2 仍在“工作” 80 data = 80 => OnConsume1 => data = 80,OnConsume2 也应该以 80 运行(忽略它可能与 60 一起工作的比赛)

【问题讨论】:

  • 没有一些代码(可能是伪代码),不清楚,至少对我来说,是什么问题。
  • 当您从生产者那里收到以下数据时:2 然后 3。如果没有收到其他数据,是否应该先处理 3,然后处理 2?或者在这种情况下应该跳过 2 ?如果你们中的一个消费者的工作速度是另一个消费者的 2 倍,所以它可以同时处理 2 和 3,而另一个消费者只能处理 3。这种情况正常吗?
  • 试图用一些伪代码来演示它。用例是游戏元素的时间线信息,每个消费者都需要知道“当前”时间。但是,我不想通过消费者同步循环,因为这会阻止其他人。因此,在您的示例中,如果 2 已被 3 覆盖,则永远不应处理它。一次只有一个值。但是如果已经处理了,没有新的,消费者就应该等待下一个。
  • 是的,您需要基于 autoresetevent 实现自己的深度 = 1 的队列,如果存在,它将替换添加的项目,然后为每个消费者创建此队列的实例。在单独的线程中运行每个消费者。生产者应将新项目放入每个消费者队列中
  • 另一种方式是使用观察者模式。在这种情况下,当收到新数据时,生产者必须在单独的线程中通知每个消费者

标签: c# multithreading unity3d mono producer-consumer


【解决方案1】:

如果您想要多个可用的值,并且具有最大深度,听起来您会想要一个堆栈/队列。或单个可为空的值,例如。

public int? value;

OnConsume1()
{
        while (running)
        {
                int myValue;
                if(value != null) // or value.HasValue
                {
                    myValue = value.Value; // or (int)value
                    value = null; // let other consumers know the value is being processed
                    // do something with data
                }
                Thread.Sleep(10);
        }
}

您需要使用 C# 的 lock 功能来保持一次只修改值的一个线程。

如果你想使用线程安全的容器,check out these

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-12-04
    • 1970-01-01
    • 1970-01-01
    • 2016-04-12
    • 1970-01-01
    • 2021-05-14
    • 2020-02-10
    相关资源
    最近更新 更多