1. ホーム
  2. .net

[解決済み] .NET - 辞書ロックとConcurrentDictionaryの比較

2022-05-16 14:17:26

質問

に関する十分な情報が見つかりませんでした。 ConcurrentDictionary 型について十分な情報が得られなかったので、ここで聞いてみようと思いました。

現在、私は Dictionary を使用して、複数のスレッド (スレッドプールからなのでスレッドの正確な量は不明) によって常にアクセスされるすべてのユーザーを保持し、同期化されたアクセスを持っています。

私は最近、.NET 4.0 にスレッドセーフなコレクションのセットがあることを知り、それは非常に喜ばしいことのようです。私は、「より効率的で管理が簡単な」オプションは何だろうと考えていました。 Dictionary を持つか、同期されたアクセスを持つ ConcurrentDictionary を使うか、あるいはすでにスレッドセーフである

.NET 4.0の参照 ConcurrentDictionary

どのように解決するのですか?

スレッドセーフなコレクションとスレッドセーフでないコレクションは、異なる方法で見ることができます。

チェックアウト時以外、店員のいない店を考えてみましょう。人々が責任を持って行動しない場合、多くの問題が発生します。たとえば、店員がピラミッドを作っている間に、客がピラミッド缶から缶を取るとしたら、大混乱になるでしょう。あるいは、2人の客が同時に同じ商品に手を伸ばしたら、どちらが勝つか?喧嘩になるのでしょうか?これはスレッドセーフでないコレクションです。問題を回避する方法はいくらでもありますが、どれも何らかのロックというか、明示的なアクセスが必要です。

一方、机に店員がいて、その店員を通してしか買い物ができないお店を考えてみましょう。列に並び、店員に品物を頼むと、店員は品物を返してくれ、あなたは列を抜けることができます。しかし、店員を独占してしまうと、後ろに並んでいる他のお客さんの怒りを買ってしまうので、注意しなければなりません。

では、こう考えてみましょう。店員が 1 人の店で、あなたが列の一番前まで行って、店員に "トイレットペーパーはありますか"と尋ね、店員が "はい"と答えた後、あなたが "わかりました、必要な量を把握したら連絡します" と言って、列の一番前に戻る頃には、もちろん店は売り切れになっていることがあるとしたら、どうしますか? このシナリオは、スレッドセーフなコレクションでは防げません。

スレッドセーフなコレクションは、たとえ複数のスレッドからアクセスされたとしても、その内部データ構造が常に有効であることを保証しています。

スレッドセーフでないコレクションには、そのような保証はありません。たとえば、あるスレッドでバイナリ ツリーに何かを追加したときに、別のスレッドがツリーのリバランスに忙しく、アイテムが追加される保証はありませんし、ツリーがその後まだ有効であることさえ、期待できないほど破損している可能性があります。

しかし、スレッドセーフなコレクションは、スレッドの順次操作がすべてその内部データ構造の同じ "snapshot" で動作することを保証するわけではなく、つまり、次のようなコードがある場合。

if (tree.Count > 0)
    Debug.WriteLine(tree.First().ToString());

の間にあるため、NullReferenceExceptionが発生する可能性があります。 tree.Counttree.First() というように、別のスレッドがツリーの残りのノードを消去しています。 First()null .

このシナリオでは、問題のコレクションが欲しいものを得るための安全な方法を持っているかどうかを確認する必要があるか、おそらく上記のコードを書き直す必要があるか、またはロックする必要があるかもしれません。