【问题标题】:Why ConcurrentDictionary has AddOrUpdate and GetOrAdd, but Dictionary has not?为什么 ConcurrentDictionary 有 AddOrUpdate 和 GetOrAdd,而 Dictionary 没有?
【发布时间】:2019-08-23 07:11:49
【问题描述】:

在.NET Framework 中,有DictionaryConcurrentDictionary。 这些提供了AddRemove等方法...

我知道当我们设计多线程程序时,为了线程安全,我们使用ConcurrentDictionary 代替Dictionary

我想知道为什么ConcurrentDictionaryAddOrUpdateGetOrAdd 和类似的方法,而Dictionary 没有。

我们总是喜欢下面的代码来从Dictionary获取对象:

var dict = new Dictionary<string, object>();
object tmp;
if (dict.ContainsKey("key"))
{
       tmp = dict["key"];
}
else
{
       dict["key"] = new object();
       tmp = new object();
}

但是当使用ConcurrentDictionary时,类似的代码只有一行。

var conDict = new ConcurrentDictionary<string, object>();
var tmp = conDict.GetOrAdd("key", new object());

我希望 .NET 有这些方法,但为什么没有呢?

【问题讨论】:

  • ConcurrentDictionary 拥有这些方法是因为它们可以防止竞争条件,而 Dictionary 不需要这些方法,因为它本质上是线程un安全的。
  • 谢谢。好的,所以 .Net 确保为开发人员提供这些方法是安全的。

标签: c# .net dictionary concurrentdictionary


【解决方案1】:

因为这样的方法是:

  1. 在并发上下文中工作的最低要求。您不能在没有锁定的情况下将GetAdd 分成两个单独的步骤,并且仍然产生正确的结果。

  2. 当为Dictionary&lt;TKey, TValue&gt; 实现时,它隐含地表示某种程度的线程安全,好像Dictionary&lt;TKey, TValue&gt; 可以正确处理这个问题。它不能,所以它只是没有实施。这并不能阻止您制作扩展方法来做类似的事情。

     public static TValue GetOrAdd<TKey, TValue>(this Dictionary<TKey, TValue> dict, TKey key, Func<TKey, TValue> valueGenerator)
     {
         //
         // WARNING: this method is not thread-safe and not intended as such.
         //
         if (!dict.TryGetValue(key, out TValue value))
         {
             value = valueGenerator(key);
    
             dict.Add(key, value);
         }
    
         return value;
     }
    

【讨论】:

  • 实际上,对于字典来说,将方法放入其中可能实际上是有意义的,不是从线程安全的角度来看,而是从优化的角度来看。字典已经计算出它期望该项目在哪个桶中,它不是,然后它可以简单地将项目直接放入该桶中。使用 tryget+add 它必须对密钥进行两次哈希处理。
  • 从这个角度来看确实如此,但在这方面,它“仅仅是”一种编码性能优化。我觉得 .NET 可以在这方面做一些认真的工作。 @LasseVågsætherKarlsen
  • 另外,在引入Dictionary&lt;TKey, TValue&gt; 时,还没有 lambdas 这样的东西。当您总是必须传递创建的实例而不是 Func&lt;&gt; 时,它的效率可能会降低。
  • @LasseV.Karlsen 出于这个原因,如果你真的需要它,很容易构建一个“更快”的 Dictionary 类。我一直想知道为什么明显的成员被排除在外。
猜你喜欢
  • 2012-05-16
  • 2019-06-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-01-23
  • 2020-12-25
  • 2012-09-07
相关资源
最近更新 更多