C# 为什么在本例中需要队列锁

C# 为什么在本例中需要队列锁,c#,multithreading,locking,syncroot,C#,Multithreading,Locking,Syncroot,我得到了如下所示的示例。我不明白为什么队列SyncRoot上也有锁,而这两个一致的算法使用同一个对象进行了整体锁定 据说队列锁定是必要的 public class CrudeThreadPool { static readonly int MaxWorkThreads = 4; static readonly int WaitTimeout = 2000; public delegate void WorkDelegate(); public CrudeThr

我得到了如下所示的示例。我不明白为什么队列SyncRoot上也有锁,而这两个一致的算法使用同一个对象进行了整体锁定

据说队列锁定是必要的

public class CrudeThreadPool
{
    static readonly int MaxWorkThreads = 4;
    static readonly int WaitTimeout = 2000;

    public delegate void WorkDelegate();

    public CrudeThreadPool() {
        stop = false;
        workLock = new Object();
        workQueue = new Queue();
        threads = new Thread[ MaxWorkThreads ];

        for( int i = 0; i < MaxWorkThreads; ++i ) {
            threads[i] =
                new Thread( new ThreadStart(this.ThreadFunc) );
            threads[i].Start();
        }
    }

    private void ThreadFunc() {
        lock( workLock ) {
            do {
                if( !stop ) {
                    WorkDelegate workItem = null;
                    if( Monitor.Wait(workLock, WaitTimeout) ) {
        
                        lock( workQueue.SyncRoot ) {
                            workItem =
                                (WorkDelegate) workQueue.Dequeue();
                        }
                        workItem();
                    }
                }
            } while( !stop );
        }
    }

    public void SubmitWorkItem( WorkDelegate item ) {
        lock( workLock ) {
            lock( workQueue.SyncRoot ) {
                workQueue.Enqueue( item );
            }

            Monitor.Pulse( workLock );
        }
    }

    public void Shutdown() {
        stop = true;
    }

    private Queue         workQueue;
    private Object        workLock;
    private Thread[]      threads;
    private volatile bool stop;
}
公共类CrudeThreadPool
{
静态只读int MaxWorkThreads=4;
静态只读int WaitTimeout=2000;
公共委托无效WorkDelegate();
公共CrudeThreadPool(){
停止=错误;
workLock=新对象();
工作队列=新队列();
线程=新线程[MaxWorkThreads];
对于(int i=0;i

锁定队列
SyncRoot
的原因是什么,即
锁定(workQueue.SyncRoot)

实际上不需要内部锁定,因为只要没有再次达到等待,锁定将被保持,并将阻止所有生产者。因此,这应该是可行的:

private void ThreadFunc() {
   do {
        if( !stop ) {
            WorkDelegate workItem = null;
            lock( workLock ) {
                if( Monitor.Wait(workLock, WaitTimeout) ) {
                    workItem = (WorkDelegate) workQueue.Dequeue();
                }
            }
            if (workItem != null) workItem();
        }
    } while( !stop );
}

public void SubmitWorkItem( WorkDelegate item ) 
{
    lock( workLock ) {
        workQueue.Enqueue( item );

        Monitor.Pulse( workLock );
    }
}
是线程场景的极好参考。
虽然这是一个典型的生产者/消费者场景,但我建议您在示例代码监视器中使用。

这只会引发队列为空的异常-仅此而已。不幸的是,这并没有变得更好-现在当队列为空时,您会在一个循环中继续循环,什么也不做,并浪费CPU资源:)在示例代码监视器中。等待和监视器。脉冲为用于发送信号。@Evk谢谢你让我停下来仔细考虑这个问题。@Slugart,正如你所说,我的结论是队列锁是不必要的。正如@Evk所说,代码从一开始就似乎很混乱。如果问题是实现生产者-消费者队列需要多少个锁对象,那么答案应该是一个。你从哪里得到的代码,为什么你认为它能工作?那代码肯定能工作。它来自一本教科书。如果你尝试实际运行这个代码,多次,你会看到它被破坏了。您将10个项目排队,但会处理随机数量的项目。有时10,有时8,有时4,有时0。写这篇文章的人不明白他在做什么(尤其是Monitor.Pulse和Monitor.Wait是如何工作的),所以没有太多的理由讨论他为什么会锁定队列访问。这只是一个例子。绝对不需要处理任何特定的项目计数。此代码被破坏,因为您可能永远不会处理放入队列中的项目。如果你把10件物品放进去,你至少会在将来某个时候把它们全部处理掉。这种代码不是这样的。使用断开的代码,您可以添加或删除队列上的锁定-这无关紧要。