在c#的多线程编程中,当需要在并发环境下操作键值对集合时,常见的方案有两种:一种是使用内置的线程安全集合ConcurrentDictionary,另一种是普通的Dictionary配合lock语句实现同步。两种方案的最终效果都是保证操作的线程安全,但性能表现会因为实现机制的不同而产生差异,尤其是在高并发场景下差异会更加明显。

两种方案的底层实现差异
Dictionary本身是线程不安全的,在多线程同时读写时会出现数据错乱甚至程序崩溃的问题,因此需要配合lock语句,让同一时间只有一个线程能执行读写操作,本质是通过互斥锁实现同步。
ConcurrentDictionary是.net框架提供的线程安全字典,内部采用了分段锁的机制,不同的数据段对应不同的锁,多个线程操作不同的数据段时可以并发执行,不需要全部排队等待同一把锁,减少了锁的竞争。
性能对比测试
下面通过一段基准测试代码,分别测试两种方案在多线程读、多线程写、混合读写场景下的性能表现。测试使用BenchmarkDotNet框架,模拟不同并发线程数的场景。
using BenchmarkDotNet.Attributes;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
[MemoryDiagnoser]
public class DictPerformanceTest
{
private const int DataCount = 10000;
private const int ThreadCount = 10;
private Dictionary<int, int> _normalDict;
private ConcurrentDictionary<int, int> _concurrentDict;
private readonly object _lockObj = new object();
[GlobalSetup]
public void Setup()
{
_normalDict = new Dictionary<int, int>();
_concurrentDict = new ConcurrentDictionary<int, int>();
}
// 测试Dictionary加lock的多线程写性能
[Benchmark]
public void NormalDictWrite()
{
Parallel.For(0, DataCount, new ParallelOptions { MaxDegreeOfParallelism = ThreadCount }, i =>
{
lock (_lockObj)
{
_normalDict[i] = i;
}
});
}
// 测试ConcurrentDictionary的多线程写性能
[Benchmark]
public void ConcurrentDictWrite()
{
Parallel.For(0, DataCount, new ParallelOptions { MaxDegreeOfParallelism = ThreadCount }, i =>
{
_concurrentDict[i] = i;
});
}
// 测试Dictionary加lock的多线程读性能
[Benchmark]
public void NormalDictRead()
{
// 先初始化数据
for (int i = 0; i < DataCount; i++)
{
lock (_lockObj)
{
_normalDict[i] = i;
}
}
Parallel.For(0, DataCount, new ParallelOptions { MaxDegreeOfParallelism = ThreadCount }, i =>
{
lock (_lockObj)
{
var val = _normalDict[i];
}
});
}
// 测试ConcurrentDictionary的多线程读性能
[Benchmark]
public void ConcurrentDictRead()
{
// 先初始化数据
for (int i = 0; i < DataCount; i++)
{
_concurrentDict[i] = i;
}
Parallel.For(0, DataCount, new ParallelOptions { MaxDegreeOfParallelism = ThreadCount }, i =>
{
var val = _concurrentDict[i];
});
}
}
测试结果分析
上述测试在10线程并发的场景下运行,得到的典型性能数据如下:
| 测试场景 | Dictionary加lock耗时 | ConcurrentDictionary耗时 | 内存分配 |
|---|---|---|---|
| 多线程写 | 约12ms | 约3ms | ConcurrentDictionary略高 |
| 多线程读 | 约8ms | 约2ms | 两者接近 |
从结果可以看出,在高并发场景下,ConcurrentDictionary的性能明显优于Dictionary加lock的方案,因为分段锁减少了线程之间的锁竞争。如果是单线程场景,Dictionary的性能会略好于ConcurrentDictionary,因为ConcurrentDictionary的分段锁机制会带来额外的开销。
选型建议
- 如果是多线程并发读写场景,优先选择ConcurrentDictionary,能获得更好的性能表现。
- 如果是单线程场景,或者并发量极低、几乎不会出现锁竞争的场景,使用Dictionary加lock即可,减少不必要的开销。
- 如果操作的是少量数据且并发量不高,两种方案的性能差异可以忽略,根据开发习惯选择即可。
需要注意的是,lock的范围要尽量小,只包裹字典的读写操作,避免把无关逻辑放在lock内部,否则会进一步加剧Dictionary加lock方案的性能劣势。
ConcurrentDictionaryDictionarylock性能对比修改时间:2026-07-06 08:42:11