【问题标题】:Is a linq query to ConcurrentDictionary Values threadsafe?对 ConcurrentDictionary Values 的 linq 查询是线程安全的吗?
【发布时间】:2010-07-09 21:19:44
【问题描述】:

假设我有以下代码:

ConcurrentDictionary<long, long> myDict= new ConcurrentDictionary<long, long>();

通常每个按键访问都是线程安全的,但是下面的 linq 查询也是线程安全的吗? 我在文档中没有找到任何内容: http://msdn.microsoft.com/en-us/library/dd287226.aspx

if myDict.Values.Any(x => !x.HasPaid))
{
  return false
}

【问题讨论】:

    标签: c# linq .net-4.0


    【解决方案1】:

    更正...我不确定您何时访问 Values 属性。在对象本身上使用 LINQ 时,它是线程安全的。


    LINQ 将使用 GetEnumerator 方法来迭代项目。

    直接来自MSDN

    从字典返回的枚举器可以安全地与字典的读取和写入同时使用,但它并不代表字典的即时快照。通过枚举器暴露的内容可能包含调用 GetEnumerator 后对字典所做的修改

    if myDict.Any(x => !x.Value.HasPaid))
    {
      return false
    }
    

    【讨论】:

      【解决方案2】:

      如前所述,ConcurrentDictionary&lt;TKey, TValue&gt;.GetEnumerator() 并不代表字典的即时快照。但是,ConcurrentDictionary&lt;TKey, TValue&gt;.Values 确实会生成即时快照。

      因此以下不等价:

      myDict.Any(x => !x.Value.HasPaid)
      myDict.Values.Any(x => !x.HasPaid)
      

      【讨论】:

      • 有趣,你有这个的来源吗? .Values 的文档没有特别提到它是一个快照:msdn.microsoft.com/en-us/library/dd381929.aspx
      • 文档不清楚,只是它返回一个集合与一个可枚举。但是看一下源代码:Values getter 调用 GetValues() 来获取锁,构造并填充一个新列表,然后释放锁。
      • 谢谢,我自己没看源码。当然,如果没有记录,这是一个可能会更改的实现细节,但仍然很有趣。
      【解决方案3】:

      ConcurrentDictionary 状态的文档 (MSDN):

      ConcurrentDictionary 的所有公共和受保护成员都是线程安全的,可以从多个线程同时使用。

      由于 .Values 属性是由 IColletion 接口规定的实现,因此它是公共的,因此是线程安全的。

      【讨论】:

      • 它是线程安全的,但获取锁会导致可能的死锁。 Count、Keys 和 IsEmpty 也是如此:geekswithblogs.net/simonc/archive/2012/02/22/…
      • 它们可以减少你的并发,但内部锁不会导致死锁。死锁需要操作相互等待,并且在锁内完成的任何事情都不能回调到您的代码中,这些代码可能会尝试做一些也需要锁的事情。
      • 真的!我站得更正了。不过,我仍然强烈推荐链接的博客条目以供参考,以了解并发集合的内部结构。
      【解决方案4】:

      到目前为止,所有答案都很棒且很有帮助,但我认为 DuneCat 在其中一个 cmets 中指出的链接值得强调:

      http://geekswithblogs.net/simonc/archive/2012/02/22/inside-the-concurrent-collections-concurrentdictionary.aspx

      具体来说......

      无锁:

      • TryGetValue
      • GetEnumerator
      • 索引器吸气剂
      • 包含密钥

      取出所有锁(锁满?):

      • 计数
      • IsEmpty
      • 钥匙
      • 价值观
      • 复制到
      • ToArray

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-09-22
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多