嵌套字典线程是否对父 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
仍然保留对该字典的引用。它可以将其作为参数传递给另一个方法。并发字典可能超出范围并被垃圾收集,而其他一些对象维护对内部字典的引用。
要点是,除了并发字典保存对对象的引用外,它不以其他方式控制该对象的行为。
如果我有一个 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
仍然保留对该字典的引用。它可以将其作为参数传递给另一个方法。并发字典可能超出范围并被垃圾收集,而其他一些对象维护对内部字典的引用。
要点是,除了并发字典保存对对象的引用外,它不以其他方式控制该对象的行为。