次のコードがあるとしましょう:
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
}
修正...いつValuesプロパティにアクセスしているのかわかりません。オブジェクト自体でLINQを使用する場合、スレッドセーフです。
LINQはGetEnumeratorメソッドを使用してアイテムをジッターします。
[〜#〜] msdn [〜#〜] から直接
ディクショナリから返された列挙子は、ディクショナリの読み取りと書き込みと同時に安全に使用できますが、ディクショナリの瞬間的なスナップショットを表すものではありません。列挙子を介して公開されるコンテンツには、GetEnumeratorが呼び出された後に辞書に加えられた変更が含まれる場合があります。
if myDict.Any(x => !x.Value.HasPaid))
{
return false
}
すでに述べたように、ConcurrentDictionary.GetEnumerator()は、辞書の瞬間的なスナップショットを表していません。ただし、ConcurrentDictionary.Valuesは、瞬間的なスナップショットを作成します。
したがって、以下は同等ではありません。
myDict.Any(x => !x.Value.HasPaid)
myDict.Values.Any(x => !x.HasPaid)
ConcurrentDictionaryの状態のドキュメント( [〜#〜] msdn [〜#〜] ):
ConcurrentDictionaryのすべてのパブリックメンバーと保護メンバーはスレッドセーフであり、複数のスレッドから同時に使用できます。
.ValuesプロパティはIColletionインターフェイスによって規定された実装であるため、パブリックであり、したがってスレッドセーフです。
これまでのすべての回答は素晴らしく、役立つものですが、コメントの1つでDuneCatが指摘したリンクは強調されていると思います。
具体的には….
ロックレス:
すべてのロックを解除します(lockfull?):