ReaderWriterLockSlim和Pulse / Wait

时间:2010-04-22 14:31:02

标签: c# .net multithreading

我是否可以将Monitor.PulseMonitor.WaitReaderWriterLockSlim结合使用?

我有一个类,我已经封装了对底层队列的多线程访问。为了排队,我获得了一个保护底层队列(以及其他几个对象)的锁,然后添加项目和Monitor.Pulse锁定的对象,以表示已将某些内容添加到队列中。

public void Enqueue(ITask task)
{
    lock (mutex)
    {
        underlying.Enqueue(task);
        Monitor.Pulse(mutex);
    }
}

在队列的另一端,我有一个后台线程,它会在消息到达队列时不断处理它们。当队列中没有项目时,它使用Monitor.Wait,以避免不必要的轮询。 (我认为这是一个很好的设计,但任何火焰(在合理范围内)如果它们帮助我学习其他方面都是受欢迎的。)

private void DequeueForProcessing(object state)
{
    while (true)
    {
        ITask task;
        lock (mutex)
        {
            while (underlying.Count == 0)
            {
                Monitor.Wait(mutex);
            }
            task = underlying.Dequeue();
        }
        Process(task);
    }
}

随着更多操作被添加到此类(要求对受保护的底层的只读访问权限),有人建议使用ReaderWriterLockSlim。我之前从未使用过该类,并假设它可以提供一些性能优势,我不反对它,但只有我能保持脉冲/等待设计。

2 个答案:

答案 0 :(得分:1)

不,基本上。它经过优化,可提供一些特定/常见方案。如果你超出这些情况,它将无法工作。如果您需要Pulse等,请改用Monitor

答案 1 :(得分:0)

在玩了一下之后(在接受了Mark的挑战之后(我同意,我的改变并不完全是基本的))我想出了这个组合:

ReaderWriterLockSlim rwls;
AutoResetEvent are;
public void Enqueue(ITask task) {
    rwls.EnterWriteLock();
    try {
        underlying.Enqueue(task);
        if (underlying.Count == 1) {
          are.Set();
        }
    } finally {
        rwls.ExitWriteLock();
    }
}
private void DequeueForProcessing(object state) {
    while (true) {
        ITask task;
        rwls.EnterWriteLock();
        try {
            while (underlying.Count == 0) {
                rwls.ExitWriteLock();
                are.WaitOne();
                rwls.EnterWriteLock();
            }
            task = underlying.Dequeue();
        } finally {
            rwls.ExitWriteLock();
        }
        Process(task);
    }
}

对于我未经训练的眼睛,这似乎符合要求(虽然它确实有点丑陋),并且它与原始版本没有太大区别。