这是另一个我讨论过的问题,但是我很好奇在使用并发字典和yield函数时会出现以下情况。
IEnumerable<int> GetValuesNotZero()
{
foreach(int value in dictionary.Values)
{
if(value != 0)
{
yield return value;
}
}
}
如果另一个线程从字典中添加/删除/更新,那么foreach循环中的值会发生什么?在我迭代时字典是否被锁定,或者我是否还有丢失添加/删除/更新值的风险?
答案 0 :(得分:2)
在您进行迭代时,如果另一个线程修改了字典,您将找到更新的值而不是异常(使用正常Dictionary<,>
)。
如果您还没有达到修改过的项目,那么您最终会完成它;否则,如果您已访问过更新的元素,则可能会错过更新的值。
来自ConcurrentDictionary.GetEnumerator
从字典返回的枚举器可以安全使用 同时读取和写入字典,但它确实如此 不代表字典的即时快照。该 通过枚举器公开的内容可能包含所做的修改 在调用GetEnumerator之后到字典。
例如,假设Thread1正在遍历字典,现在位于第3位。如果在第7位修改了元素,则您将找到修改后的值。另一方面,如果它修改了位置1的元素,你就不会注意到它。 (忘记字典是无序的;使用位置来更好地理解)。
我刚刚意识到您的代码循环遍历Dictionary.Values
(感谢@Svick在评论中提及);只有循环通过字典,上面的答案才会成立。当您在Values
属性中进行迭代时,您实际上正在遍历快照。如果字典在同一时间更新,您将不会注意到它。