IDictionary 和 ConcurrentDictionary 的线程安全注意事项
Thread-safety considerations with IDictionary and ConcurrentDictionary
这个问题主要是学术问题 - 我理解这不一定是实用代码。
考虑一下这段代码,其中线程安全是一个问题:
// In the constructor
IDictionary<string, string> myDictionary = new ConcurrentDictionary<string, string>();
...
// Elsewhere in the class
myDictionary.Add("foo", "bar");
我的总体问题:从并发的角度来看,这是如何处理的?
这会被认为是线程安全的吗?如果是,为什么?我问是因为(已知的)线程安全方法是 AddOrUpdate
- 我无法使用 IDictionary
访问它。 CLR "smart enough" 知道这里发生了什么吗?我在这里缺少 属性 继承吗,.Add
调用是否可以突变为 .AddOrUpdate
调用 "under the hood"?
这里不涉及CLR。 ConcurrentDictionary
隐式实现接口 IDictionary<TKey, TValue>
,你可以看到它为 IDictionary.Add
做了什么 here:
void IDictionary<TKey, TValue>.Add(TKey key, TValue value)
{
if (!TryAdd(key, value))
{
throw new ArgumentException(GetResource("ConcurrentDictionary_KeyAlreadyExisted"));
}
}
因此它调用 TryAdd
(ConcurrentDictionary
的 "safe" 方法),如果无法添加密钥 - 抛出异常,表明具有此类密钥的条目已存在。
它仍然是 "thread-safe",因为您不会有讨厌的副作用,您将使用常规字典并从多个线程向其中添加项目。如果您准备好应对此类异常 - 您可以安全地将带有 Add
的项目从多个线程添加到此类字典中。
这个问题主要是学术问题 - 我理解这不一定是实用代码。
考虑一下这段代码,其中线程安全是一个问题:
// In the constructor
IDictionary<string, string> myDictionary = new ConcurrentDictionary<string, string>();
...
// Elsewhere in the class
myDictionary.Add("foo", "bar");
我的总体问题:从并发的角度来看,这是如何处理的?
这会被认为是线程安全的吗?如果是,为什么?我问是因为(已知的)线程安全方法是 AddOrUpdate
- 我无法使用 IDictionary
访问它。 CLR "smart enough" 知道这里发生了什么吗?我在这里缺少 属性 继承吗,.Add
调用是否可以突变为 .AddOrUpdate
调用 "under the hood"?
这里不涉及CLR。 ConcurrentDictionary
隐式实现接口 IDictionary<TKey, TValue>
,你可以看到它为 IDictionary.Add
做了什么 here:
void IDictionary<TKey, TValue>.Add(TKey key, TValue value)
{
if (!TryAdd(key, value))
{
throw new ArgumentException(GetResource("ConcurrentDictionary_KeyAlreadyExisted"));
}
}
因此它调用 TryAdd
(ConcurrentDictionary
的 "safe" 方法),如果无法添加密钥 - 抛出异常,表明具有此类密钥的条目已存在。
它仍然是 "thread-safe",因为您不会有讨厌的副作用,您将使用常规字典并从多个线程向其中添加项目。如果您准备好应对此类异常 - 您可以安全地将带有 Add
的项目从多个线程添加到此类字典中。