嵌套字典线程是否对父 ConcurrentDictionary 安全?

Are nested Dictionaries thread safe from parent ConcurrentDictionary?

如果我有一个 ConcurrentDictionary 对象 ConcurrentDictionary<int, Dictionary<string, string>>() dict;,当对外部 ConcurrentDictionary 执行操作时,嵌套的 Dictionary 是否被锁定?

场景:外部ConcurrentDictionary outerDict正在执行

outerDict.Add(42, new Dictionary<string, string>())

在一个线程上,并且在另一个线程上(同时),内部 Dictionary 正在执行

outerDict[30].Add("hello", "world").

上述场景中外层ConcurrentDictionary和嵌套Dictionary的修改是并发,还是同时进行?

当然不是,它们是具有不同访问规则的不同词典。

但是您的示例很好,因为您正在从不同的线程访问不同的词典。如果您改为这样做:

outerDict[30]["a"] = "b"; // in thread 1
outerDict[30]["g"] = "h"; // in thread 2

您很快就会 运行 遇到问题。

这里有4个操作:

  • 正在创建一个新对象。这样做没有并发影响,因为当时没有其他人引用该对象。
  • 正在将对象添加到并发字典中。没问题,因为它是并发字典。
  • 正在访问并发字典中的第 30 个条目。没问题,因为它是并发字典
  • 向第 30 个字典添加新值:有问题,如果另一个线程也引用了第 30 个字典。

A ConcurrentDictionary<TKey, TValue> 是线程安全的。它的设计使多个线程可以安全地使用该字典中的键。它不能也不会将该线程安全扩展到存储在字典中的值。

并发字典存储对内部字典的引用。但是内部字典并不“知道”任何引用它的东西。据它所知,它只是一个 Dictionary<string, string>.

尽管并发字典引用了内部字典,但它不以任何方式“拥有”或控制该内部字典。

您可以编写以下代码:

var innerDictionary = new Dictionary<string, string>();
outerDict.Add(42, innerDictionary);

在这种情况下 innerDictionary 仍然保留对该字典的引用。它可以将其作为参数传递给另一个方法。并发字典可能超出范围并被垃圾收集,而其他一些对象维护对内部字典的引用。

要点是,除了并发字典保存对对象的引用外,它不以其他方式控制该对象的行为。