是对ConcurrentDictionary值的线程安全的linq查询吗?

时间:2010-07-09 21:19:44

标签: c# linq .net-4.0

假设我有以下代码:

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
}

4 个答案:

答案 0 :(得分:38)

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


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

直接来自MSDN

  

从字典返回的枚举器可以安全地与字典的读写一起使用,但它并不代表字典的即时快照。通过枚举器公开的内容可能包含在调用GetEnumerator后对字典进行的修改

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

答案 1 :(得分:35)

如前所述,ConcurrentDictionary.GetEnumerator()不代表字典的时刻快照。但是,ConcurrentDictionary.Values确实生成了一个时刻快照。

因此以下内容并不等同:

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

答案 2 :(得分:10)

ConcurrentDictionary的文档声明(MSDN):

  

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

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

答案 3 :(得分:4)

到目前为止,所有的答案都很棒,很有帮助,但我认为DuneCat在其中一条评论中指出的链接强调:

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

具体.....

<强>无锁:

  • TryGetValue
  • GetEnumerator
  • 索引器getter
  • 的containsKey

取出每一个锁(锁定?):

  • 计数
  • 的IsEmpty
  • CopyTo从
  • ToArray的