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

Chr*_*ris 43 c# linq .net-4.0

假设我有以下代码:

ConcurrentDictionary<long, long> myDict= new ConcurrentDictionary<long, long>();
Run Code Online (Sandbox Code Playgroud)

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

if myDict.Values.Any(x => !x.HasPaid))
{
  return false
}
Run Code Online (Sandbox Code Playgroud)

chi*_*emp 40

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


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

直接来自MSDN

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

if myDict.Any(x => !x.Value.HasPaid))
{
  return false
}
Run Code Online (Sandbox Code Playgroud)


Kev*_*vin 37

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

因此以下不等同于:

myDict.Any(x => !x.Value.HasPaid)
myDict.Values.Any(x => !x.HasPaid)
Run Code Online (Sandbox Code Playgroud)

  • 除了返回集合与可枚举之外,文档不清楚.但是看看源代码:Values getter调用GetValues()获取锁,构造和填充新列表,并释放锁. (9认同)
  • 啊谢谢你,我自己没有看源代码。当然,如果没有记录,这是一个可能会更改的实现细节,但仍然很有趣。 (3认同)

小智 11

ConcurrentDictionary的文档声明(MSDN):

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

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

  • 它们可以降低并发性,但内部锁定不会导致死锁.死锁需要彼此等待的操作,并且锁内部完成的任何操作都不能回调到可能尝试执行需要锁定的操作的代码. (9认同)
  • 它是线程安全的,但获取锁定导致可能的死锁.Count,Keys和IsEmpty也是如此:http://geekswithblogs.net/simonc/archive/2012/02/22/inside-the-concurrent-collections-concurrentdictionary.aspx (3认同)

RJB*_*RJB 7

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

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

具体来说.....

无锁:

  • 尝试获取值
  • 获取枚举器
  • 索引器吸气剂
  • 包含密钥

取出每个锁(lockfull?):

  • 数数
  • 是空的
  • 钥匙
  • 价值观
  • 复制到
  • 数组