5

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

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

  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 等了这么多次?

4

3 回答 3

13

对于只写负载,Monitor 比 ReaderWriterLockSlim 便宜,但是,如果您模拟读取比写入大得多的读取 + 写入负载,则 ReaderWriterLockSlim 应该执行 Monitor。

于 2009-01-02T23:47:37.330 回答
0

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

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

于 2009-01-02T16:08:58.817 回答
0

你怎么知道是什么导致了糟糕的表现?您无法猜测,唯一的方法是进行某种分析。

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

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

于 2009-01-02T20:30:31.143 回答