为什么ReadOnlyDictionary不是线程安全的?

12
我正在寻找一个只读字典,可以从多个线程中访问。虽然ConcurrentDictionary提供了这样的功能,但我不想有额外的开销和奇怪的API。
尽管.NET 4.5提供了这样的类,但文档指出只有静态调用是安全的。
我在想为什么?

线程安全 ConcurrentDictionary<TKey, TValue> 的所有公共和受保护成员都是线程安全的,可以从多个线程同时使用。 - Ken Cheung
3
@KenCheung:你的评论与问题关系不明确。问题表明OP已经了解ConcurrentDictionary<,>,但正在询问ReadOnlyDictionary<,>的安全性。 - Jon Skeet
1个回答

14

ReadOnlyDictionary 只是包装在其他字典周围的一个封装器。因此,它的线程安全性与基础字典一样。

特别地,如果有一个线程正在修改基础字典,而另一个线程从包装器中读取,那么就不能保证安全。

如果您想要一个ReadOnlyDictionary,使其从所有角度看起来都是不可变的,您可以创建原始字典的副本,创建一个ReadOnlyDictionary包装器,并且不在任何地方保留副本的引用。仅进行读取操作,则应该是线程安全的。当然,如果键或值类型是可变的,则会打开第二个“线程不安全”的问题。


4
澄清一下,只读并不意味着线程安全。如果字典根据读取使用情况重新排列项目会怎么样?据我所知,BCL字典没有这样做,但我在某个地方读到Scripting.Dictionary会将最后读取的项目移动到桶中的第一个位置。 - adrianm
1
@adrianm:是的,没错。但是你可以包装一个从未被修改过的System.Collections.Generic.Dictionary,那样就没问题了。 - Jon Skeet
1
@MaxBarraclough:Dictionary 的文档明确指出:“只要集合没有被修改,Dictionary<TKey,TValue> 可以同时支持多个读取器。”因此,如果 ReadOnlyDictionary 包装了一个 Dictionary,并且在初始化后从未被修改,我认为这是可以的。 - Jon Skeet
@TonyVitabile 但是这会有影响,不是吗?我猜你需要用同样的锁来保护读取方法?你只是想确保在尝试读取某些内容时添加或删除操作已经完成。 - El Mac
@ElMac 嗯,不,它并没有伤害到我,因为我只是在问一个假设性的问题。我目前并没有需要这样的结构;我只是在阅读其他评论时突然想到这个问题而已。现在我知道了答案,如果将来我确实需要一个,我可以正确地编写它。 - Tony Vitabile
显示剩余5条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接