2017-03-10 4 views
1

lockキーワードは、領域をスレッド、つまりマルチスレッド環境で実行する必要がある場合に使用します。スレッドの残りの部分はその領域を待機します。スタティックコレクションのロックの動作方法

私は複数のクラスで使用されているコレクションIList<Student> student=new List<Student>()を持っています。

一部の場所では、オブジェクトがリストに追加され、一部の場所ではオブジェクトが削除されています。これにより、一貫性のない動作が発生します。

マルチスレッド環境でクラスxのコレクションをロックすると、コレクションはすべてのクラスに対してロックされ、異なるクラスのすべてのスレッドはロックを待機します。

Class StaticClass 
{ 
Public static IList<Student> student=new List<Student>(); 
} 


Class ClassA 
{ 
//add an item in the collection 
} 

Class ClassB 
{ 
//delete an item in the collection 
} 

Class ClassC 
{ 
//lock the collection here 

     lock (StaticClass.student) 
     { 

      foreach (ConnectionManager con in ConnectionManager.GetAllStudents()) 
      { 
      con.Send(offlinePresence); 
      } 
     } 

} 

ClassCでコレクションをロックすると、classAとClassBの他のスレッドは待機しますか?コレクションがロックされているため、forループが実行されるまで誰もコレクション内の項目を追加または削除できません。

+0

[ConcurrentBag Class](https://msdn.microsoft.com/en-us/library/dd381779(v=vs.110).aspx) – Fabio

+2

は基本的にはyesですが、別の ' (またはリストを 'readonly'にして)ロックされている間に参照されたオブジェクトが変更されないようにします。 – slawekwin

+0

ループの場合は、リストのコピー(新しいインスタンス)を作成して追加、削除することができますループ中にクラスは影響を受けません。 'foreach(学生の中の生徒のリスト。リスト())...' – Fabio

答えて

0

アセンブリからSystem.Collections.Generic.SynchronizedCollection<T>をご覧ください。

Fabioが述べたように、ConcurrentBagも機能しますが、ConcurrentBagも機能しますが、それにアクセスするスレッドごとに別々のリストコンテキストが作成されます。アイテムを試して削除すると、キューのように機能します。あなた自身のスレッドのリストにある項目を使い切ったら、スレッドセーフな方法で他のスレッドのリストから項目を "盗み"ます。

あなたの仕事には、私はSynchronizedCollectionが良いと思っています。

0

コードがオブジェクトのロックを取得しても、そのオブジェクトへの他のスレッドからのアクセスはブロックされません。このオブジェクトに起こる唯一のことは、ロックが解放されない限り、他のスレッドが同じオブジェクトに対するロックを取得できないことです。

別のプレーンオブジェクトをロックのターゲットとして予約するのが一般的です。

例では、コードが最初に明示的にロックしない限り、他のスレッドはList<Student>オブジェクトにアクセスできます。

ロックすると、重大なパフォーマンス上の問題(互いを待っているスレッド)が発生し、多くの場合、明示的に実装する必要はありません。 .NET FrameworkのコレクションクラスConcurrentをご覧ください。

関連する問題