ConcurrentDictionary Keys 或 Values 属性是线程安全的

编程入门 行业动态 更新时间:2024-10-16 02:31:43
本文介绍了ConcurrentDictionary Keys 或 Values 属性是线程安全的的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧! 问题描述

对 ConcurrentDictionary 的线程安全有疑问.从 API 中,我看到枚举器是线程安全的,但对于键和值属性,我没有看到相同的内容.我的问题是:

Have a question regarding thread safety with ConcurrentDictionary. From the API, I see that the enumerator is thread-safe, but I don't see the same for keys and values properties. My question is:

当有其他线程同时修改 Keys 或 Values 集合时,它是否安全?

Is it safe to loop over the Keys or Values collection when there are other threads modifying it concurrently?

推荐答案

虽然我喜欢文档,但我倾向于在有疑问或我觉得我可能假设太多时用一个小程序来验证事情.

While I do like the documentation, I tend to verify things with a small program when in doubt or I feel that I might be assuming too much.

以下代码验证您确实可以安全地枚举值集合,同时从单独的线程向正在枚举的线程添加或删除键.这不会导致通常的集合被修改异常.更详细地说,这里有几个测试用例

The following code verifies that indeed you can enumerate the values collection safely while adding or removing keys from a separate thread to that on which the enumeration is taking place. This will not cause the usual collection was modified exceptions. In more detail, here are a couple of test cases

案例 1:枚举值并删除一个键

如果您遵循以下顺序:

  • 从线程开始枚举值集合
  • 从我们尚未枚举的其他线程中删除一个键
  • 在原线程上继续枚举

观察到的行为是删除的键确实会被枚举,因为它在我们开始枚举时存在于值集合中.不会引发任何异常.

The observed behavior is that the removed key will indeed be enumerated since it existed in the values collection when we started the enumeration. No exception will be raised.

案例 2:枚举值并添加键

  • 从线程开始枚举值集合
  • 从我们尚未枚举的不同线程添加一个新密钥
  • 在原线程上继续枚举

观察到的行为是添加的键不会被枚举,因为当我们开始枚举它时,它不存在于值集合中.无论我们使用 TryAdd 还是通过直接分配给字典(即 dictionary[key] = value)来添加都不会引发异常.

The observed behavior is that the added key will not be enumerated since it did not exist in values collection when we started to enumerate it. No exception will be raised whether we use TryAdd or add by assigning directly to the dictionary ie dictionary[key] = value.

示例代码

这是演示这两种情况的示例程序:

Here is the sample program that demonstrates both cases:

ConcurrentDictionary<int, int> dictionary = new ConcurrentDictionary<int, int>(); // Seed the dictionary with some arbitrary values; for (int i = 0; i < 30; i++) { dictionary.TryAdd(i, i); } // Reader thread - Enumerate the Values collection Task.Factory.StartNew( () => { foreach (var item in dictionary.Values) { Console.WriteLine("Item {0}: count: {1}", item, dictionary.Count); Thread.Sleep(20); } } ); // writer thread - Modify dictionary by adding new items and removing existing ones from the end Task.Factory.StartNew( () => { for (int i = 29; i >= 0; i--) { Thread.Sleep(10); //Remove an existing entry int removedValue; if (dictionary.TryRemove(i, out removedValue)) Console.WriteLine("Removed item {0}", removedValue); else Console.WriteLine("Did not remove item {0}", i); int iVal = 50 + i*2; dictionary[iVal] = iVal; Thread.Sleep(10); iVal++; dictionary.TryAdd(iVal, iVal); } } ); Console.ReadKey();

这是发布模式下的输出:

更多推荐

ConcurrentDictionary Keys 或 Values 属性是线程安全的

本文发布于:2023-11-12 10:47:19,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1581273.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:线程   属性   ConcurrentDictionary   Keys   Values

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!