web-dev-qa-db-ja.com

.NETのスレッドセーフコレクション

スレッドセーフなコレクション(たとえば、Set)が必要な今日の標準は何ですか。自分で同期しますか、それとも本質的にスレッドセーフなコレクションがありますか?

65
ripper234

.NET 4.0 Frameworkは、 System.Collections.Concurrent Namespace にいくつかのスレッドセーフコレクションを導入しています。

ConcurrentBag <T>
オブジェクトのスレッドセーフで順序付けられていないコレクションを表します。

ConcurrentDictionary <TKey、TValue>
複数のスレッドが同時にアクセスできる、キーと値のペアのスレッドセーフなコレクションを表します。

ConcurrentQueue <T>
スレッドセーフな先入れ先出し(FIFO)コレクションを表します。

ConcurrentStack <T>
threadスレッドセーフな後入れ先出し(LIFO)コレクションを表します。


.NET Frameworkの他のコレクションは、デフォルトではスレッドセーフではないため、操作ごとにロックする必要があります。

lock (mySet)
{
    mySet.Add("Hello World");
}
98
dtb

.NET 4.0より前の.Netのほとんどのコレクションはスレッドセーフではありません。同期を処理するには、いくつかの作業を自分で行う必要があります。 http://msdn.Microsoft.com/en-us/library/573ths2x.aspx

記事からの引用:

次のいずれかの方法を使用して、コレクションクラスをスレッドセーフにすることができます。

Synchronizedメソッドを使用してスレッドセーフラッパーを作成し、そのラッパーを介して排他的にコレクションにアクセスします。

クラスにSynchronizedメソッドがない場合は、クラスから派生し、SyncRootプロパティを使用してSynchronizedメソッドを実装します。

コレクションにアクセスするとき、SyncRootプロパティでC#のロックステートメント(Visual BasicではSyncLock)などのロックメカニズムを使用します。

ルートプロパティの同期
ステートメントのロック

Object thisLock = new Object();
......
lock (thisLock)
{
    // Critical code section
}

.net 4.0で導入された System.Collections.Concurrent 名前空間

ブロッキングコレクション
同時バッグ
同時キュー
同時辞書
Ordable Partitioner
パーティショナー
パーティションT

18
kemiller2002

.NET 4は、System.Collections.Concurrentの下に一連のスレッドセーフコレクションを提供します。

4
Kai Wang

System.Collections.Concurrentの非常に便利なクラスに加えて、.Netにも適用される、ほとんど読み取りがまれな変更シナリオ(または、頻繁ではあるが非同時書き込みがある場合)の1つの標準的な手法が呼び出されます Copy-on-write .

高度な並行プログラムで望ましいプロパティがいくつかあります。

  • コレクションオブジェクトインスタンス自体は不変です(つまり、スレッドセーフで、ロックせずに安全に列挙できます)
  • 変更には必要なだけ時間がかかります。読み取りのパフォーマンスと同時実行性は影響を受けません
  • 総称的に実装 で、スレッドセーフではないデータ構造を

制限:同時書き込みがある場合、変更を再試行する必要があるため、同時書き込みが多くなるほど効率が低下します。 (つまり 楽観的同時実行 作業中)

EditScott Chamberlainのコメントは、別の制限があることを思い出させてくれました:データ構造が巨大で、変更が頻繁に発生する場合、書き込み時コピーがメモリ消費量とコピーのCPUコストの両方の観点から禁止されます。

1