.NET TIPS

スレッド・セーフなコレクション・オブジェクトを作成するには?

デジタルアドバンテージ 遠藤 孝信
2005/03/04

 .NET Frameworkのクラス・ライブラリには、リストやスタック、キューといった基本的なコレクション・クラスが用意されているが、これらはすべてスレッド・セーフではない。つまり1つのコレクション・オブジェクト(以下、コレクションと略)に対して、複数のスレッドから同時に操作する場合と、それらすべての操作を順に1つずつ行う場合とでは、異なる処理結果を生み出す可能性があるということだ。

 このような状況を避けるためには、コレクションを操作する前にそのコレクションをロックすればよいが(具体的にはSyncRootプロパティを利用する)、コレクション・クラスのSynchronizedメソッドを利用すればスレッド・セーフなコレクションを作成することができる。Synchronizedメソッドを持つコレクション・クラス(System.Collections名前空間のクラス)には、次のようなクラスがある。

・ArrayListクラス ・Hashtableクラス ・Queueクラス
・SortedListクラス ・Stackクラス  

 例えば、ArrayListオブジェクトの場合には、次のようにしてスレッド・セーフなコレクションを得ることができる。

ArrayList dangerousList = new ArrayList();
ArrayList safeList = ArrayList.Synchronized(dangerousList);

 この場合には、safeListオブジェクトに対するすべてのメソッドの呼び出しは同期を取りながら実行されるため、そのオブジェクトのロックは不要となる。

Synchronizedメソッドにより作成されるラッパー・オブジェクト

 Synchronizedメソッドが返すオブジェクトは、実際には各コレクション・クラスを継承したクラスのオブジェクトであり、そのクラスはコレクション・クラスのラッパー・クラスとなる。

 例えばArrayListクラスの場合には、そのラッパー・クラスの名前は実際にはSyncArrayListクラスであり、そのAddクラスは次のような実装となっている。

class SyncArrayList : ArrayList {
  ArrayList _list;       // 本来のArrayListオブジェクト
  object _objectForLock; // ロック用のオブジェクト

  public override int Add(object value) {
    ……
    lock (this._objectForLock) {
      return this._list.Add(value);
    }
    ……
  }
  ……
}
ArrayListクラスに対するスレッド・セーフなラッパー・クラスのAddメソッド(C#)
このクラスはArrayListクラスのprivateな入れ子クラスとなっており、Synchronizedメソッド経由でしかインスタンス化できない。

 このクラスでは、ArrayListクラスのすべてのメソッドやプロパティをオーバーライドしている。すべてのメソッドやプロパティは、このAddメソッドのように同期のためのオブジェクト(上記の例ではobjectForLock)をロックしてから、ラップしているArrayListオブジェクトを操作するようになっているため、それを呼び出す側でのロックが不要となるわけだ。

 なお、コレクションがスレッド・セーフかどうか(Synchronizedメソッドにより作成されたかどうか)は、そのオブジェクトのIsSynchronizedプロパティによりチェックできる。End of Article

カテゴリ:クラス・ライブラリ 処理対象:コレクション
カテゴリ:クラス・ライブラリ 処理対象:マルチスレッド
使用ライブラリ:ArrayListクラス(System.Collections名前空間)
使用ライブラリ:Hashtableクラス(System.Collections名前空間)
使用ライブラリ:Queueクラス(System.Collections名前空間)
使用ライブラリ:SortedListクラス(System.Collections名前空間)
使用ライブラリ:Stackクラス(System.Collections名前空間)
 
この記事と関連性の高い別の.NET TIPS
キューを利用するには?[C#/VB]
配列のサイズを変更するには?
Windowsフォーム上のコントロールの位置やサイズを固定するには?
ArrayListとListの違いとは?[C#/VB]
このリストは、(株)デジタルアドバンテージが開発した
自動関連記事探索システム Jigsaw(ジグソー) により自動抽出したものです。
generated by

「.NET TIPS」


Insider.NET フォーラム 新着記事
  • 第2回 簡潔なコーディングのために (2017/7/26)
     ラムダ式で記述できるメンバの増加、throw式、out変数、タプルなど、C# 7には以前よりもコードを簡潔に記述できるような機能が導入されている
  • 第1回 Visual Studio Codeデバッグの基礎知識 (2017/7/21)
     Node.jsプログラムをデバッグしながら、Visual Studio Codeに統合されているデバッグ機能の基本の「キ」をマスターしよう
  • 第1回 明瞭なコーディングのために (2017/7/19)
     C# 7で追加された新機能の中から、「数値リテラル構文の改善」と「ローカル関数」を紹介する。これらは分かりやすいコードを記述するのに使える
  • Presentation Translator (2017/7/18)
     Presentation TranslatorはPowerPoint用のアドイン。プレゼンテーション時の字幕の付加や、多言語での質疑応答、スライドの翻訳を行える
@ITメールマガジン 新着情報やスタッフのコラムがメールで届きます(無料)

注目のテーマ

Insider.NET 記事ランキング

本日 月間