私の理解に基づいて、C#の配列を指定して、複数のスレッドから同時に配列を反復処理の行為は、あるスレッド安全な操作。
することにより、配列を反復処理 Iは、によって、アレイ内のすべての位置を読んで意味昔ながらのfor
ループ。各スレッドは単に配列内のメモリ位置のコンテンツを読み取っているだけで、誰も何も書き込んでいないため、すべてのスレッドが一貫した方法で同じものを読み取ります。
これは、上で書いたことを実行するコードの一部です。
public class UselessService
{
private static readonly string[] Names = new [] { "bob", "alice" };
public List<int> DoSomethingUseless()
{
var temp = new List<int>();
for (int i = 0; i < Names.Length; i++)
{
temp.Add(Names[i].Length * 2);
}
return temp;
}
}
したがって、私の理解では、メソッドDoSomethingUseless
はスレッドセーフでありstring[]
、をスレッドセーフタイプ(ImmutableArray<string>
たとえば)に置き換える必要はありません。
私は正しいですか?
次に、のインスタンスがあるとしますIEnumerable<T>
。基本となるオブジェクトが何であるかはわかりません。オブジェクトを実装していることがわかっているだけなIEnumerable<T>
ので、foreach
ループを使用してオブジェクトを反復処理できます。
私の理解に基づいて、このシナリオでは、複数のスレッドからこのオブジェクトを同時に反復することがスレッドセーフな操作であるという保証はありません。別の言い方をするとIEnumerable<T>
、異なるスレッドからインスタンスを同時に反復すると、オブジェクトの内部状態が破壊され、オブジェクトが破損する可能性があります。
私はこの点で正しいですか?
クラスのIEnumerable<T>
実装はどうArray
ですか?スレッドセーフですか?
言い換えれば、次のコードはスレッドセーフですか?(これは上記とまったく同じコードですが、foreach
ループの代わりにループを使用して配列が反復されfor
ます)
public class UselessService
{
private static readonly string[] Names = new [] { "bob", "alice" };
public List<int> DoSomethingUseless()
{
var temp = new List<int>();
foreach (var name in Names)
{
temp.Add(name.Length * 2);
}
return temp;
}
}
IEnumerable<T>
.NET基本クラスライブラリのどの実装が実際にスレッドセーフであるかを示すリファレンスはありますか?
Array
すべてのスレッドが配列を読み取るだけである限り、配列(つまり)の反復処理はスレッドセーフになります。と同じでList<T>
、おそらく他のすべてのMicrosoftが作成したコレクションです。しかしIEnumerable
、列挙子でスレッドセーフではないことを行う独自のものを作成することは可能です。したがって、実装IEnumerable
するすべてがスレッドセーフであるという保証はありません。
foreach
列挙子だけでは機能しません。コンパイラーは、コレクションが配列であることを示す静的な型情報がある場合、列挙子の生成をスキップし、for
ループのように配列に直接アクセスするだけであることを知るのに十分スマートです。同様に、コレクションがのカスタム実装をサポートしている場合は、GetEnumerator
を呼び出す代わりにその実装が使用されIEnumerable.GetEnumerator
ます。foreach
入稿のみを行うという考え方IEnumerable/IEnumerator
は誤りです。
volatile
ため、変数に対する最新の更新が得られるとは限りません。鮮度について推論する代わりに、書き込みの並べ替え方法にどのような制限が課さ volatile
れるかについて推論します。