gpt4 book ai didi

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

转载 作者:IT王子 更新时间:2023-10-29 03:57:28 24 4
gpt4 key购买 nike

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

当有其他线程同时修改它时,遍历 KeysValues 集合是否安全?

最佳答案

虽然我确实喜欢这些文档,但我倾向于在有疑问时使用小程序来验证事情,或者我觉得我可能假设得太多了。

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

案例 1:枚举值并删除键

如果您遵循以下顺序:

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

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

案例 2:枚举值并添加键

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

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

示例代码

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

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();

这是 Release模式下的输出:

Console output

关于c# - ConcurrentDictionary Keys 或 Values 属性是线程安全的,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10479867/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com