我正在尝试了解何时使用Dictionary vs ConcurrentDictionary,因为我对“词典”所做的更改之一存在问题。
我有这个词典
private static Dictionary<string, Side> _strategySides = null;
在构造函数中,我将一些键和值添加到我创建的词典中,如此
_strategySides.Add("Combination", Side.Combo);
_strategySides.Add("Collar", Side.Collar);
此代码很好,并且已经在所有环境中运行了一段时间。当我添加
_strategySides.Add("Diagonal", Side.Diagonal);
此代码开始破坏,例外“索引超出了数组的范围。”在字典上。然后我进入了ConcurrentDictionary的概念及其用途,我需要在我的案例中选择ConcurrentDictionary而不是我的案例,因为它是一个多线程应用程序。
所以我向你所有的大师提出的问题是,为什么这些天它都没有抛出异常,而是在我向字典添加内容时开始。任何有关这方面的知识将不胜感激。
答案 0 :(得分:1)
正如您所提到的,您有多线程应用程序。字典不是线程安全的,并且在代码中的某处,当您向其添加项目时,您正在同时阅读字典 - &gt; IndexOutOfboundsException
。
documentation中提到了这一点:
字典可以同时支持多个读者,只要 集合未被修改。即便如此,通过集合进行枚举 本质上不是一个线程安全的过程。在极少数情况下 枚举与写访问争用,集合必须是 在整个枚举期间锁定。允许收集 您必须通过多个线程访问以进行读写 实现自己的同步。有关线程安全的替代方法,请参阅 ConcurrentDictionary。
答案 1 :(得分:1)
查看此问题的答案:c# Dictionary lookup throws "Index was outside the bounds of the array"
似乎在字典上接收此错误特定于线程安全违规。链接的答案提供了两种处理问题的方法,一种是并发字典。
如果我不得不猜测为什么它之前没有发生:你在构造函数中为静态对象添加条目,这意味着只有1个编写器,还没有读者。
你的新条目可能是在构造函数之外添加的?正在尝试进行此写操作时,另一个线程可能正在读取,并且是不允许的。
答案 2 :(得分:1)
Dictionary
不是线程安全的,如果你在从多个线程访问时修改它,可能会发生各种奇怪的事情,包括出现“工作”......直到它没有。使用锁保护它,或使用专为多线程使用而设计的数据结构(即ConcurrentDictionary
)。
那么为什么它“起作用” - 这很难明确地知道,但我的赌注是要么根本没有看到问题(即内部字典状态已损坏但你没有注意到它由于你的使用模式),或者只是在执行时间上“幸运”(例如,您可能无意中通过调试器“同步”了线程)。
重点是:不管它是什么,你都不能依赖它!即使“错误的东西”似乎“有效”,你也必须做“正确的事”。这就是多线程编程的本质。