多线程更新不同键时Dictionary的线程安全性问题问询
字典线程安全问题:仅更新不同键时是否安全?
我有一个特殊的使用场景,需要用同一方法上下文中另一个字典中的可用值来更新当前字典的每个键。虽然我知道字典通常不具备线程安全性,但我想确认:如果能确保不会同时更新两个不同的键,是否可以认为它是线程安全的?该场景可简化为以下xUnit测试,我运行了一小时未出现任何失败:
[Theory] [InlineData(10000)] [InlineData(100000)] [InlineData(1000000)] [InlineData(10000000)] public void Transform(int a) { var nums = Enumerable.Range(1, a).ToDictionary(i => i); foreach (var num in nums.Keys.AsParallel()) { nums[num] = num * num; Assert.True(num > 0); } }
- 即使保证不同时更新不同键,.NET的
Dictionary<TKey, TValue>也不是线程安全的。 - 字典的内部结构(比如哈希桶数组、计数变量等)并非只在修改特定键时才会变动。哪怕你只修改不同键的值,某些全局操作依然会引发线程冲突——比如当字典负载因子达标触发扩容时,整个哈希表会被重新组织,这个过程是全局的,多线程同时操作必然导致数据损坏或异常。
- 你的测试没失败只是巧合:当前测试场景可能没触发扩容,或者
AsParallel()的线程调度刚好没在关键节点产生冲突,但这不能代表线程安全。一旦字典规模更大、负载更高,或者线程调度更密集,肯定会出现问题。 - 正确处理方式:如果要在多线程环境下安全操作字典,要么使用线程安全的
ConcurrentDictionary<TKey, TValue>,要么给所有字典访问(包括读和写)操作加锁,确保同一时间只有一个线程操作字典。
内容的提问来源于stack exchange,提问作者Marcel Batista
相关产品推荐
相关产品推荐

