私がこの実験を書いたのは、共有データに複数のスレッドで同時にアクセスすることは大したことではないことを誰かに示すためです。驚いたことに、作成したスレッドの数に関係なく、同時実行の問題を作成できず、値は常にバランスの取れた値 0 になりました。インクリメント演算子がスレッドセーフではないことがわかっているため、メソッドが存在します。Interlocked.Increment()
と同様ですInterlocked.Decrement()
(ここにも記載されていますIs the ++ operator thread safe?)。
インクリメント/デクリメント演算子がスレッド セーフでない場合、以下のコードが問題なく実行され、期待値になるのはなぜですか?
以下のスニペットは、2,000 のスレッドを作成します。データが複数のスレッドによって同時にアクセスされることを保証するために、1,000 が常に増加し、1,000 が常に減少します。さらに悪いことに、通常のプログラムではスレッド数がほとんどないということです。しかし、同時実行の問題を作成するために誇張された数値にもかかわらず、値は常に 0 のバランスのとれた値になります。
static void Main(string[] args)
{
Random random = new Random();
int value = 0;
for (int x=0; x<1000; x++)
{
Thread incThread = new Thread(() =>
{
for (int y=0; y<100; y++)
{
Console.WriteLine("Incrementing");
value++;
}
});
Thread decThread = new Thread(() =>
{
for (int z=0; z<100; z++)
{
Console.WriteLine("Decrementing");
value--;
}
});
incThread.Start();
decThread.Start();
}
Thread.Sleep(TimeSpan.FromSeconds(15));
Console.WriteLine(value);
Console.ReadLine();
}
誰かが私に説明を提供してくれることを願っています。そうすれば、スレッドセーフなソフトウェアを作成するための私のすべての努力が無駄ではないこと、またはおそらくこの実験に何らかの欠陥があることがわかります。また、すべてのスレッドをインクリメントして、i++ の代わりに ++i を使用してみました。値は常に期待値になります。