編集:誰でもこれを見て、私はあなたが議論を見てみることをお勧めします。配列リストのオブジェクトを変更する読者スレッドに関する重要な点は、共有コレクションに関するこのクラス全体の質問にとって非常に重要です(そして、この場合、私はたぶん「全体を大きくロックする」と思うでしょう)むしろ、私はそれらの変更の詳細な分析をすることなく、ここに与えるそれでも、次はまだいくつかのケースで作業することができたアプローチより:。。
のパターンは、私は次のことを行うだろう、あなたが記述することを書き込みして読み込むために
ArrayListがal
と呼ばれているとしましょう。すべての読み込みでは、すべてのスレッドの安全性を無視して読んでいます(私の狂気にはメソッドがあります)。やるウルド:ArrayListには、複数の読者のために安全であるため、
ArrayList temp = new ArrayList(al);//create copy of al
/* code to update temp goes here */
al = temp;//atomic overwrite of al.
Thread.MemoryBarrier();//make sure next read of al isn't moved by compiler or from stale cache value.
al
のコピーは、安全です。アトミックな参照を上書きするため、割り当ては安全です。実際にはほとんどの現行システムでそれをスキップすることはできますが(理論的には少なくとも理論的には必要であり、それを二度と推測しないでください)、おそらくメモリ障壁があることを確認する必要があります。
arraylistのほとんどの共有使用では、書き込みが非常に高価になるため、これはかなり恐ろしいことです。しかし、それは読書よりも60,000,000倍少ないと言われているので、バランスが合理的です。このアプローチの安全な読書の
注:
ため、私は同様のケースを考えるの誤った仮定をしていました。 次は安全である:
for(object obj in al)
DoSomething(obj);
DoSomething
は長い時間がかかることがあります場合でも。これは、GetEnumerator()
を一度呼び出してから、その間にal
が変更されても、同じリストに関連付けられた列挙子で動作します(これは古いですが、安全です)。
次は安全ではありません。
for(int i = 0; i < al.Count; ++i)
DoSomething(al[i]);//
Count
は安全ですが、それはあなたがal
はわずか20アイテムを持っているときにal[43]
を呼び出すことを意味しますal[i]
に着く時間によって古い可能性があります。それはその時点で変更されている可能性があるため、
それはあなたがal
で行う第二のものにより決定するBinarySearch
、Contains
またはIndexOf
の結果を使用しても安全BinarySearch
、Clone
、Contains
、IndexOf
とGetRange
ではなくを呼び出すためにも安全です。
次も安心です。私たちはただの参照をコピーし、al
をコピーしていないので、これは本当に安いです
ArrayList list = al;
for(int i = 0; i != list.Count; ++i)
DoSomething(list[i]);
DoSomethingElse(list);
DoSomethingReallyComplicated(list);
for(int i = 0; i != list.Count; ++i)
SureWhyNotLetsLoopAgain(list[i]);
注意。 list
で行うことはすべて安全です。古くなった場合でも、古いリストの1つのスレッドの独自のバージョンであり、間違ってはいけないので、安全です。
So. foreach
(すべて私が間違って想定していた場合)のいずれかを実行し、上記の安全な方法で呼び出した結果を返します(al
で別の操作を行うかどうかを決めるのに使用しません)。al
ローカル変数に変換し、それに基づいて動作します。
別本当に重要な注意点は、ライター・スレッドは、実際に任意のプロパティを設定したり、ArrayListの中に含まれるオブジェクトのいずれかの上の任意の非スレッドセーフのメソッドを呼び出すかどうかです。そうであれば、スレッド同期の問題が発生していないことから、数十を持つことになりました!
この場合、arraylistだけでなく、変更可能なオブジェクト(.Append("abc")
StringBuilder
を呼び出す方法は完全に新しいものに置き換えられない)を心配する必要がありますオブジェクトstr = "abc"
の変更str
)。 - 幸せな日あなたの配列リストで不変オブジェクトを持って
- :
は4つの安全の可能性があります。
- オブジェクトを変更することはできますが、変更することはできません。また、である必要があります。
- あなたはスレッドセーフなオブジェクトを持っています - 大丈夫ですが、少なくとも1つのスレッディング問題のセットは、この問題が扱うものより複雑です。
- 書き込みと読み取りの両方のために各オブジェクトをロックします - 競合するロックはこのような細かいロックではあまりありませんが、これは独自の重さを持ち、実際にはデフォルトよりも優れていません「ちょうどロック)とにかく争われていないとき、ロックが安いです。
あなたの代わりにリスト