当遇到频繁读取而写入很少的场景时,很多人推荐用读写锁取代lock,理由是性能问题。正好搜到老赵的这篇文章http://www.cnblogs.com/jeffreyzhao/archive/2009/11/12/concurrent-cache-performance-improvement-1-immutable-hash-table.html,里面有一个性能测试,我顺便添加了一个lock的测试:
object lockobj = new object();
CodeTimer.Time("lock", iteration, () =>
{
foreach (var i in source)
{
lock(lockobj)
{
var ignore = dict[i];
}
}
});
结果一测,出乎我的意料,lock的性能竟然跟不加锁差不多,比ReaderWriterLockSlim还要高不少。连续测试几次,都是如此。
Read Free
Time Elapsed: 531ms
CPU Cycles: 5,000,000
Gen 0: 0
Gen 1: 0
Gen 2: 0
lock
Time Elapsed: 768ms
CPU Cycles: 7,500,000
Gen 0: 0
Gen 1: 0
Gen 2: 0
ReaderWriterLockSlim
Time Elapsed: 1,378ms
CPU Cycles: 12,656,250
Gen 0: 0
Gen 1: 0
Gen 2: 0
ReaderWriterLock
Time Elapsed: 2,700ms
CPU Cycles: 25,937,500
Gen 0: 0
Gen 1: 0
Gen 2: 0
真是奇怪了,不过我并不认为网上大家的分析是错误的,应该是我的测试代码写错了。请大家帮我看看,测试代码是哪里错了,应该怎么写?还是有其他方面的原因,才造成这个结果?下面是完整的测试代码,大家可以亲自运行一下看看。
我明白了,问题的关键是lock同时只允许一个线程访问,而读写锁允许同时有多个线程读取。这个测试只是一个线程的情况下,没有意义。一旦有多个线程同时读取,读写锁的优势就出来了。