我有一个IDictionary<TKey,TValue>
实现,在内部持有另一个Dictionary<TKey, TValue>
,并通过密钥的HashCode将该插入分发到invidual子词典。有了16个子词典,4核机器上的冲突数量相当低。
对于并行插入,我使用ReaderWriterLockSlim
锁定Add方法,仅锁定单个子词典:
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使用率和糟糕的性能。所以我用Monitor监视了ReaderWriterLockSlim(即lock
关键字)。
CPU使用率现在接近100%,性能提高了一倍多。
我的问题是:为什么CPU使用量会增加?碰撞次数不应该改变。是什么让ReaderWriterLock.EnterWriteLock等了这么多次?
答案 0 :(得分:13)
对于只写加载,Monitor比ReaderWriterLockSlim便宜,但是,如果你模拟read + write load,其中read远大于write,那么ReaderWriterLockSlim应该执行Monitor。
答案 1 :(得分:0)
我不是大师,但我的猜测是RWLS更倾向于重度争用(例如,数百个线程),而Monitor
则更倾向于那些一次性同步问题。
我个人使用TimerLock
类,它使用带有超时参数的Monitor.TryEnter
。
答案 2 :(得分:0)
你怎么知道导致糟糕表现的原因?你无法猜测它,唯一的方法是进行某种分析。
如何处理父集合的锁定或是否为常量?
也许你需要添加一些调试输出,看看到底发生了什么?