C#のスレッドセーフな並行コレクション(Concurrent Collections)徹底解説
.NET Framework 4では、System.Collections.Concurrent名前空間が新たに導入されました。この名前空間には、スレッドセーフかつ高いスケーラビリティを実現する複数のコレクションクラスが含まれています。これらは「並行コレクション(Concurrent Collections)」と呼ばれ、複数のスレッドから同時に安全にアクセスできる点が最大の特徴です。
従来のList<T>やDictionary<TKey,TValue>などをマルチスレッド環境で扱う場合は、lock文などによる明示的な同期処理が必要でしたが、並行コレクションを使えばその負担から解放され、デッドロックや競合状態(レースコンディション)のリスクを大幅に減らせます。
C#で利用できる主な並行コレクション一覧
| No. | 型と説明 |
|---|---|
| 1 | BlockingCollection<T> あらゆる型に対して境界設定(バウンディング)とブロッキング機能を提供します。生産者・消費者パターンの実装に最適です。 |
| 2 | ConcurrentDictionary<TKey,TValue> キーと値のペアを格納する辞書のスレッドセーフ実装です。 |
| 3 | ConcurrentQueue<T> FIFO(先入れ先出し)キューのスレッドセーフ実装です。 |
| 4 | ConcurrentStack<T> LIFO(後入れ先出し)スタックのスレッドセーフ実装です。 |
| 5 | ConcurrentBag<T> 順序を持たない要素のコレクションのスレッドセーフ実装です。 |
| 6 | IProducerConsumerCollection<T> BlockingCollectionで使用できる型が実装すべきインターフェースです。 |
ConcurrentStack<T>の基本的な使い方
ここでは、スレッドセーフなLIFO(後入れ先出し)コレクションであるConcurrentStack<T>の使い方を見ていきましょう。
1. ConcurrentStackのインスタンスを作成する
ConcurrentStack<int> s = new ConcurrentStack<int>();
2. Pushメソッドで要素を追加する
s.Push(1); s.Push(2); s.Push(3); s.Push(4); s.Push(5); s.Push(6);
Pushメソッドはスタックの先頭に要素を追加します。通常のStack<T>と同じ感覚で使えますが、内部で適切に同期処理が行われるため、マルチスレッドから呼び出しても安全です。
3. サンプルプログラム
次の例では、ConcurrentStackに要素を追加した後、IsEmptyプロパティを使ってスタックが空かどうかを判定しています。
例
using System;
using System.Collections.Concurrent;
class Demo{
static void Main (){
ConcurrentStack<int> s = new ConcurrentStack<int>();
s.Push(50);
s.Push(100);
s.Push(150);
s.Push(200);
s.Push(250);
s.Push(300);
if (s.IsEmpty){
Console.WriteLine("スタックは空です!");
}
else {
Console.WriteLine("スタックは空ではありません");
}
}
}出力結果
スタックは空ではありません
まとめ
並行コレクションを活用することで、マルチスレッドアプリケーションにおける共有データの管理を安全かつ効率的に行えます。特にConcurrentStack<T>は、Push(追加)・TryPop(取り出し)・IsEmpty(空判定)といった直感的なAPIを備えており、既存のStack<T>からの移行も容易です。マルチスレッド処理でコレクションを扱う際は、ぜひSystem.Collections.Concurrent名前空間の活用を検討してみてください。
-
Javaでコレクションをスレッドセーフにする方法
java.utilパッケージのCollectionsクラスには、コレクション専用に動作するユーティリティメソッドが多数用意されており、ポリモーフィックなアルゴリズムを含むさまざまな追加操作を利用できます。 マルチスレッド環境でコレクションを安全に扱いたい場合、このクラスが提供する同期化メソッドを使うことで、既存のコレクションを簡単にスレッドセーフなものへ変換できます。以下に、synchronizedCollection()系メソッドの主なバリアントを示します。 No.メソッドと説明 1 static <T> Collection<T> synchronized
-
Pythonの辞書はスレッドセーフ?GILの仕組みとマルチスレッドでの注意点
Pythonの辞書はスレッドセーフなのか?結論から言うと、Pythonの辞書(dict)は基本的にスレッドセーフです。さらに言えば、辞書だけでなく、リストやセットなどPythonの組み込み型は、単一の操作レベルであればすべてスレッドセーフであると言えます。なぜスレッドセーフなのか:GIL(グローバルインタプリタロック)その理由は、CPythonが採用しているGIL(Global Interpreter Lock:グローバルインタプリタロック)という仕組みにあります。GILは、一度に1つのスレッドだけがPythonバイトコードを実行できるように制御するロックであり、このおかげで複数のスレッドが同