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

假设我有以下代码:

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
}
Chris asked 2020-07-25T15:37:43Z
4个解决方案
40 votes

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


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

直接来自MSDN

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

if myDict.Any(x => !x.Value.HasPaid))
{
  return false
}
chilltemp answered 2020-07-25T15:38:31Z
37 votes

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

因此,以下内容并不等效:

myDict.Any(x => !x.Value.HasPaid)
myDict.Values.Any(x => !x.HasPaid)
Kevin answered 2020-07-25T15:38:56Z
11 votes

ConcurrentDictionary状态(MSDN)的文档:

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

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

Jan C. de Graaf answered 2020-07-25T15:39:25Z
4 votes

到目前为止,所有答案都是非常有用的,但我认为DuneCat在其中一项评论中指出的链接值得强调:

[HTTP://geek是with blog上.net/Simon C/archive/2012/02/22/inside-他和-concurrent-collections-concurrent dictionary.aspx]

特别.....

无锁:

  • TryGetValue
  • GetEnumerator
  • 索引器获取器
  • ContainsKey

取出所有锁(全锁?):

  • 计数
  • 是空的
  • 按键
  • 价值观
  • 复制到
  • 数组
RJB answered 2020-07-25T15:40:44Z
translate from https://stackoverflow.com:/questions/3216636/is-a-linq-query-to-concurrentdictionary-values-threadsafe