スレッドセーフなコレクションと非スレッドセーフなコレクションは、別の見方ができます。
レジ以外に店員がいない店舗を考えてみましょう。人々が責任を持って行動しないと、多くの問題が発生します。たとえば、店員が現在ピラミッドを構築しているときに、顧客がピラミッド缶から缶を取り出したとしましょう。または、2 人の顧客が同時に同じ商品に到達した場合、どちらが勝ちますか? 戦いはありますか?これはスレッドセーフではないコレクションです。問題を回避する方法はたくさんありますが、いずれもある種のロック、または何らかの方法での明示的なアクセスが必要です。
一方、デスクに店員がいる店を考えてみましょう。店員を通してしか買い物をすることができません。あなたが列に並び、彼にアイテムを頼むと、彼がそれを持ってきて、あなたは列から出ます。複数のアイテムが必要な場合は、各往復で覚えている限りの数のアイテムしかピックアップできませんが、店員を独り占めしないように注意する必要があります。これにより、後ろに並んでいる他の顧客を怒らせることになります.
これを考えてみましょう。店員が一人の店で、列の一番前まで行って、店員に「トイレットペーパーはありますか」と聞いたら、「はい」と答えたら、「わかりました。」いくら必要かわかったらまた連絡します」と言って、列の先頭に戻る頃には、もちろん店は売り切れている可能性があります. このシナリオは、スレッドセーフ コレクションによって防止されません。
スレッドセーフなコレクションは、複数のスレッドからアクセスされた場合でも、その内部データ構造が常に有効であることを保証します。
スレッドセーフでないコレクションには、そのような保証はありません。たとえば、あるスレッドでバイナリ ツリーに何かを追加した場合、別のスレッドがツリーのバランスを取り直すのに忙しくしているときに、アイテムが追加されるという保証はありません。
ただし、スレッドセーフなコレクションは、スレッド上の順次操作がすべてその内部データ構造の同じ「スナップショット」で機能することを保証しません。つまり、次のようなコードがある場合:
if (tree.Count > 0)
Debug.WriteLine(tree.First().ToString());
tree.Count
とtree.First()
の間で、別のスレッドがツリー内の残りのノードをクリアしたため、NullReferenceException が発生する可能性があります。つまり、First()
が を返しnull
ます。
このシナリオでは、問題のコレクションに必要なものを安全に取得できる方法があるかどうかを確認する必要があります。おそらく、上記のコードを書き直す必要があるか、ロックする必要があるかもしれません。