发布于2026-07-23 阅读(0)
扫一扫,手机访问
在.NET Framework 4.0中,增加了一个新成员——ConcurrentDictionary。它继承自 Dictionary,所以大部分标准字典操作(添加、查找、删除)都能照常使用。但不一样的是,它额外提供了一些线程安全的方法,比如 TryAdd、TryUpdate、TryRemove 等。换句话说,如果你在写多线程代码,又需要用到字典,那它几乎就是为你量身定做的。
1. 泛型字典类本质上是哈希表,通过键来映射值,检索速度非常快——前提是键的哈希算法质量过关。
2. TValue 可以是值类型、数组、类,甚至其他任意类型,很灵活。
3. 在一个类的实例里,如果有个属性是字典,我们通常不加思考就用 Dictionary。但当这个属性被提升为 static(类级别)时,就必须考虑线程安全性了——因为它可能被多个线程同时访问。当然,如果这个对象只是只读的,那无所谓。但如果可写,就得上锁。
4. 一旦允许多个线程同时对字典进行读写,你就得自己实现同步。读写并行时加锁不可避免,但锁一加,性能就跟着降下来了。
1. 这个类专为多线程场景设计,表示可由多个线程同时访问的键值对集合,且线程安全。
2. ConcurrentDictionary 是 .NET 4.0 推出的一套线程安全集合中的一员,同批亮相的还有 ConcurrentStack、ConcurrentQueue 等。它们对应的单线程(线程不安全)版本就是 Queue、Stack 和 Dictionary。
3. 用法和 Dictionary 大同小异,但多了几个关键方法。它属于 System.Collections.Concurrent 命名空间。
在 .NET 4.0 之前,多线程环境下想用 Dictionary,只能自己手写线程同步来保证安全,别无他选。而 4.0 之后,微软帮你把这件事干了——直接上 ConcurrentDictionary,再也不用纠结“Dictionary + Locks”的组合了。
那么,加锁后的 Dictionary 和 ConcurrentDictionary 到底谁更靠谱?性能又差多少?来看一段实测代码。
string res = ""; var concurrentDictionary = new ConcurrentDictionary(); var dictionary = new Dictionary (); dictionary.TryAdd(1, "aa"); concurrentDictionary.TryAdd(1,""); var sw = new Stopwatch(); sw.Start(); Parallel.For(0, 1000000, i => // 并行循环 { lock (dictionary) { dictionary[i] = new Random().Next(1000, 9999).ToString(); } }); sw.Stop(); Console.WriteLine("加锁写入dictionary {0}", sw.Elapsed); // writing to dictionary with a lock: 00:00:00.0633939 sw.Restart(); Parallel.For(0, 1000000, i => { concurrentDictionary[i] = new Random().Next(1000, 9999).ToString(); }); sw.Stop(); Console.WriteLine("concurrentdictionary写入时长 : {0}", sw.Elapsed); sw.Restart(); Parallel.For(0, 1000000, i => { lock (dictionary) { res = dictionary[i]; } }); sw.Stop(); Console.WriteLine("读取dictionary耗时: {0}", sw.Elapsed); sw.Restart(); Parallel.For(0, 1000000, i => { res = concurrentDictionary[i]; }); sw.Stop(); Console.WriteLine("读取concurrentdictionary耗时: {0}", sw.Elapsed); Console.ReadLine();
结果如下:
从测试结果来看,无论是读取还是写入,ConcurrentDictionary 都明显胜出,而且没有出现线程安全问题。当然,不同环境、不同负载下数据可能略有差异。但趋势很明显:多核多线程场景下,ConcurrentDictionary 的性能表现会更好。
说起来,面试时如果被问到“Dictionary 怎么解决线程安全问题”,能答出 ConcurrentDictionary 一定是加分项。
需要提醒的是,有网友指出 ConcurrentDictionary 在某些极端情况下依然可能存在线程安全问题。目前没遇到过,但使用时保持警惕总没错。
TryAdd 的用法很实用:往字典里添加元素时,如果指定的 key 已经存在,用 Add 方法会抛出异常。而 TryAdd 则不会——它只会返回 false,程序继续平稳运行。
dictionary.TryAdd(1, "aa"); concurrentDictionary.TryAdd(1,"");
注意,ConcurrentDictionary 只支持 TryAdd,而普通 Dictionary 既支持 Add 也支持 TryAdd(从 .NET 4.0 开始也添加了 TryAdd 方法)。
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
正版软件
正版软件
正版软件
正版软件
正版软件
1
2
3
7
8