C#工作线程唤醒竞争条件

时间:2013-09-23 13:43:35

标签: c# multithreading race-condition

以下代码使用后台工作线程逐个处理工作项。每当工作项用尽时,工作线程就开始等待ManualResetEvent。主线程定期添加新工作项并唤醒工作线程。

唤醒机制具有竞争条件。如果主线程添加了一个新项,而工作线程位于*所指示的位置,则工作线程不会被唤醒。

是否有一种简单而正确的方法来唤醒没有此问题的工作线程?

    ManualResetEvent m_waitEvent;

    // Worker thread processes work items one by one
    void WorkerThread()
    {
        while (true)
        {
            m_waitEvent.WaitOne();
            bool noMoreItems = ProcessOneWorkItem();
            if (noMoreItems)
            {
                // *
                m_waitEvent.Reset();    // No more items, wait for more
            }
        }
    }

    // Main thread code that adds a new work item
    AddWorkItem();  
    m_waitEvent.Set();  // Wake worker thread

2 个答案:

答案 0 :(得分:3)

您使用的是错误的同步机制。而不是MRE只使用信号量。然后,信号量将表示尚待处理的项目数。您可以将其设置为添加一个,或者等待它将其减少一个。没有if,你总是做每个信号量动作,因此没有竞争条件。

那就是说,你可以完全避免这个问题。您可以自己使用BlockingCollection,而不是自己管理同步原语。让生产者添加项目,消费者使用它们。同级将由该类为您完成,并且可能比您的实现更有效。

答案 1 :(得分:0)

我倾向于使用当前的工作项计数器并递增和递减该计数器。您可以将处理器线程转换为循环,查看该计数器然后休眠而不是运行一次并完成。这样,无论您在何时添加项目,您都可以从正在处理的项目中获得1个睡眠周期。