3

私の質問は、他の人に確認したいようなものなので、正しい答えが得られたと確信しています. コレクションの列挙など、スレッドセーフでない操作を行う場合、そのコレクションに Synchronized メソッドが存在する場合は、それを呼び出すのが最善の方法です。

例えば:var syncAL = ArrayList.Synchronized( myAL );

そして、心配することなく次のようなことができます:

foreach (var item in syncAL){
  // Do something
}

今、私は個人的に ArrayLists を実際には使用していません。これは単なる例でしたが、通常の List の場合、Synchronized メソッドは存在しないため、ここでのベスト プラクティスは次のようになります。

lock (list.SyncRoot){
 // non thread-safe operation, e.g:
 list.ForEach(item => Console.WriteLine(item.ToString()));
}

もちろん、独自の任意のオブジェクトを作成できますが、複数のクラスでコレクションオブジェクトを使用している場合は、それらすべてのクラスでロックするために同じオブジェクトを使用していることを確認する必要があります。それを行うための非常に快適な方法のように。

チームの開発のヒントとして書いたものを追加する前に、それが本当にベストプラクティスであり、欠けているものがないことを確認したい:)

これについての私の理解の源: MSDN SyncRoot

4

2 に答える 2

4

そして、心配することなく次のようなことができます:

foreach (var item in syncAL){
  // Do something
}

いいえ。MSDNから:

コレクションの列挙は、本質的にスレッドセーフな手順ではありません。コレクションが同期されている場合でも、

そして核となる質問に:

それが本当にベストプラクティスであることを確認したい

いいえ、それは時代遅れの慣習です。SyncRoot は に限定されてICollectionおり、 ではサポートされていないことに注意してくださいICollection<T>。新しいコレクション ( List<>) はサポートしていません。これが主な手がかりです。

于 2013-04-10T21:40:19.027 に答える
3

ArrayList.Synchronized ラッパーでコレクションをラップしても、列挙はスレッド セーフになりません。MSDNでは、次のように明示的に述べています。

...コレクションが同期されている場合でも、他のスレッドは引き続きコレクションを変更できるため、列挙子は例外をスローします。

したがって、最良のアプローチは、依然として SyncRoot でロックするか、System.Collections.Concurrent 名前空間のスレッドセーフなコレクションを使用することです。

ArrayList.Synchronized の内部実装は、内部クラス SyncArrayList のインスタンスを作成するだけで、次のように、あらゆる操作に対して SyncRoot をロックします。

  public override int Add(object value)
  {
    lock (this._root)
      return this._list.Add(value);
  }
于 2013-04-10T21:36:58.477 に答える