並列プログラミング向けのデータ構造
.NET には、同時実行コレクション クラスのセット、軽量な同期プリミティブ、遅延初期化用の型など、並列プログラミングに役立つ型がいくつかあります。 これらの型は、タスク並列ライブラリや PLINQ などの任意のマルチスレッド アプリケーション コードで使うことができます。
同時実行コレクション クラス
System.Collections.Concurrent 名前空間のコレクション クラスは、できる限りロックを回避するスレッドセーフな追加と削除の操作を提供し、ロックが必要なときは粒度の細かいロックを使います。 同時実行コレクション クラスでは、項目にアクセスするときにロックを取得するユーザー コードが不要です。 複数のスレッドがコレクションの項目を追加および削除するシナリオでは、同時実行コレクション クラスを使うと、System.Collections.ArrayList や System.Collections.Generic.List<T> (ユーザー実装のロックを使用) などの型に対するパフォーマンスが大幅に向上します。
次の表は、同時実行コレクション クラスの一覧です。
[種類] | [説明] |
---|---|
System.Collections.Concurrent.BlockingCollection<T> | System.Collections.Concurrent.IProducerConsumerCollection<T> を実装するスレッド セーフなコレクションに、ブロッキングと範囲指定の機能を提供します。 利用できるスロットがない場合、またはコレクションがいっぱいの場合は、プロデューサー スレッドがブロックします。 コレクションが空の場合は、コンシューマー スレッドがブロックします。 この型は、コンシューマーとプロデューサーによる非ブロッキング アクセスもサポートします。 BlockingCollection<T> は、基底クラスとして、または IEnumerable<T> をサポートする任意のコレクション クラスにブロッキングと範囲指定を提供するバッキング ストアとして、使うことができます。 |
System.Collections.Concurrent.ConcurrentBag<T> | スケーラブルな追加と取得の操作を提供するスレッドセーフなバッグの実装です。 |
System.Collections.Concurrent.ConcurrentDictionary<TKey,TValue> | 同時実行のスケーラブルなディクショナリ型です。 |
System.Collections.Concurrent.ConcurrentQueue<T> | 同時実行のスケーラブルな FIFO キューです。 |
System.Collections.Concurrent.ConcurrentStack<T> | 同時実行のスケーラブルな LIFO スタックです。 |
詳しくは、「スレッド セーフなコレクション」を参照してください。
同期プリミティブ
System.Threading 名前空間の同期プリミティブを使うと、従来のマルチスレッド コードに見られるような高コストのロック メカニズムを回避することで、細かいコンカレンシーを設定でき、高速のパフォーマンスが提供されます。
次の表は、同期型の一覧です。
Type | 説明 |
---|---|
System.Threading.Barrier | 各タスクが到着を通知し、一部または全部のタスクが到着するまでブロックすることができるポイントを提供することにより、複数のスレッドが 1 つのアルゴリズムで並列に動作できるようにします。 詳細については、「バリア」を参照してください |
System.Threading.CountdownEvent | 簡単なランデブー メカニズムを提供することにより、フォークと結合のシナリオを簡略化します。 詳しくは、「CountdownEvent」をご覧ください。 |
System.Threading.ManualResetEventSlim | System.Threading.ManualResetEvent と同様の同期プリミティブです。 ManualResetEventSlim の方が軽量ですが、プロセス内通信にしか使えません。 |
System.Threading.SemaphoreSlim | リソースまたはリソースのプールに同時にアクセスできるスレッドの数を制限する同期プリミティブです。 詳しくは、「Semaphore と SemaphoreSlim」をご覧ください。 |
System.Threading.SpinLock | ロックを取得しようとしているスレッドがクォンタムを生成する前にしばらくループ ("スピン") で待機するようになる、相互排他ロック プリミティブです。 ロックの待機が短いと予想されるシナリオでは、他のロック形式より SpinLock の方がよいパフォーマンスを提供します。 詳しくは、「SpinLock」をご覧ください。 |
System.Threading.SpinWait | 指定された時間だけスピンし、スピン カウントを超過した場合は最終的にスレッドを待機状態にする、小型で軽量の型です。 詳しくは、「SpinWait」をご覧ください。 |
詳細については、次を参照してください。
遅延初期化クラス
遅延初期化では、オブジェクトのメモリは必要になるまで割り当てられません。 遅延初期化を使うと、オブジェクトの割り当てがプログラムの有効期間全体に均等に分散されるので、パフォーマンスが向上します。 Lazy<T> 型をラッピングすることにより、任意のカスタム型で遅延初期化を有効にできます。
次の表は、遅延初期化型の一覧です。
Type | 説明 |
---|---|
System.Lazy<T> | 軽量でスレッドセーフの遅延初期化を提供します。 |
System.Threading.ThreadLocal<T> | スレッドごとに遅延初期化された値を提供し、各スレッドは初期化関数を遅延して呼び出します。 |
System.Threading.LazyInitializer | 専用の遅延初期化インスタンスを割り当てる必要のない静的メソッドを提供します。 代わりに、参照を使って、ターゲットがアクセスされたときは初期化されているようにします。 |
詳細については、「限定的な初期化」を参照してください。
例外集約
System.AggregateException 型を使うと、別のスレッドで同時にスローされた複数の例外をキャプチャし、1 つの例外として結合スレッドに戻すことができます。 System.Threading.Tasks.Task 型、System.Threading.Tasks.Parallel 型、PLINQ は、この目的に AggregateException を広範に使います。 詳細については、「例外処理」および「方法: PLINQ クエリの例外を処理する」を参照してください。
関連項目
.NET