2011-11-10 2 views
0

私はthis bookのコードサンプルを試していましたが、ポストデクリメント演算子がアトミックではないことを証明する必要があります。コードはLinqPadに入力したものです。ポストデクリメントがアトミックでないことを実証する... FAIL

void Main() { 
    var count = 0; 
    do { 
    _x = 10000; 
    for (int i = 0; i < 100; i++) { 
     new Thread(Go).Start(); 
    } 
    Thread.Sleep(1000); 

    Console.WriteLine("Try "+ count); 
    count++; 
    } while (_x == 0); 
    Console.WriteLine(_x); 
} 

int _x = 10000; 
void Go() { for (int i = 0; i < 100; i++) _x--; } 

アイデアは、すべてのスレッドが終了したときにロックすることなく、複数のスレッドで並列に_xをデクリメントすることは、他の_xの値に0を導く可能性があることです。

私の問題は、どれだけ長く試してみても、常に結果として0が得られるということです。 私は2つの異なるコンピュータ(Windows 7と2つの異なるバージョン)で2つの異なるバージョンの.NETでコードを実行しています。

私はここで何が欠けていますか?

+3

繰り返し回数を増やしてください。スレッドが速く終了する可能性があります。これは、別のスレッドをスピンアップする前に完了している可能性があります。だから、100の代わりに、100000かそれ以上のものを数えます。 –

+0

@ LasseV.Karlsenはい。それはそれだった。私は 'Go'で繰り返し回数を増やしました。最初の試行では0以外の結果が得られました。ありがとうございました。 – Andris

+0

スレッドを最初に作成し、ループで開始します。またはプールを使用します。 –

答えて

1

Lasse V. Karlsenが示唆しているように、私はGoに100000回の追加を追加しました。このコードは、最初の試行では正常に動作します。私はまた、スレッドの作成をループから外し、Henk Holtermanが提案したようにスレッド数を減らしました。

void Main() 
{ 
    var count = 0; 
    do { 
    _x = 1000000; 
    var threads = Enumerable.Range(0,10).Select (_ => new Thread(Go)).ToList(); 

    foreach (var t in threads) 
    { 
     t.Start(); 
    } 

    Thread.Sleep(1000); 
    Console.WriteLine("Try "+ count); 
    count++; 
    } while (_x == 0); 
    Console.WriteLine(_x); 
} 

int _x; 
void Go() { for (int i = 0; i < 100000; i++) _x--; } 

コードが正常に動作するようになりました。

関連する問題