【问题标题】:ReaderWriterLockSlim vs. MonitorReaderWriterLockSlim 与监视器
【发布时间】:2009-01-02 16:04:29
【问题描述】:

我有一个 IDictionary<TKey,TValue> 实现,它在内部拥有 n 个其他 Dictionary<TKey, TValue> 并通过键的 HashCode 将插入分发到各个子字典。有 16 个子字典,在 4 核机器上冲突的数量非常少。

对于并行插入,我用 ReaderWriterLockSlim 锁定了 Add-method,只锁定了单个子字典:

  public void Add(TKey key, TValue value)
        {
            int poolIndex = GetPoolIndex(key);
            this.locks[poolIndex].EnterWriteLock();
            try
            {
                this.pools[poolIndex].Add(key, value);
            }
            finally
            {
                this.locks[poolIndex].ExitWriteLock();
            }
        }

当使用四个线程插入项目时,我只得到了大约 32% 的 cpu 使用率和糟糕的性能。所以我用监视器(即lock 关键字)替换了 ReaderWriterLockSlim。 CPU 使用率现在接近 100%,性能提高了一倍以上。

我的问题是:为什么 CPU 使用率会增加?碰撞次数不应改变。是什么让 ReaderWriterLock.EnterWriteLock 等了这么多次?

【问题讨论】:

    标签: c# multithreading locking readerwriterlock


    【解决方案1】:

    对于只写负载,Monitor 比 ReaderWriterLockSlim 便宜,但是,如果您在读取远大于写入的情况下模拟读取 + 写入负载,则 ReaderWriterLockSlim 应该优于 Monitor。

    【讨论】:

      【解决方案2】:

      我不是专家,但我的猜测是 RWLS 更适合处理激烈的争用(例如,数百个线程),而 Monitor 更适合那些一次性同步问题。

      我个人使用TimerLock 类,该类使用带有超时参数的Monitor.TryEnter

      【讨论】:

        【解决方案3】:

        您如何知道导致性能不佳的原因?您无法猜测,唯一的方法是进行某种分析。

        你如何处理父集合的锁定或者它是恒定的?

        也许您需要添加一些调试输出,看看实际发生了什么?

        【讨论】:

        • 集合本身没有被锁定,只有子词典。性能好坏之间的唯一变化是监视器替换了 ReaderWriterLock。
        • 你说的改进可能只是一个副作用。唯一知道的方法是进行某种分析。也许带有调试跟踪。如果父集合未锁定并且发生更改,则可能无法正常工作。
        猜你喜欢
        • 1970-01-01
        • 2010-12-15
        • 1970-01-01
        • 2016-11-04
        • 1970-01-01
        • 1970-01-01
        • 2011-12-01
        • 1970-01-01
        • 2013-05-06
        相关资源
        最近更新 更多