2011-11-10 33 views
0

我試着從this book中得到一個代碼示例,它應該證明post-decrement操作符不是原子的。代碼就像我輸入LinqPad一樣。證明post-decrement不是原子...失敗

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。 我已經在兩臺不同的計算機(包括Windows 7)和兩個不同版本的.NET上運行代碼,兩者都給了我相同的結果。

我在這裏錯過了什麼?

+3

增加迭代次數,最有可能的是線程完成得如此之快,以至於在你旋轉另一個之前,前一個已經結束,永遠不會並行運行。所以,而不是100,數到100000或更大的東西。 –

+0

@ LasseV.Karlsen是的。就是這樣。我在'Go'中增加了迭代次數,並且在第一次嘗試時得到了非0的結果。謝謝。 – Andris

+0

先創建線程,然後在循環中啓動它們。或使用池。你只需要幾個,而不是1000. –

回答

1

根據Lasse V. Karlsen的建議,我在Go中添加了100000個元素。代碼現在可以按照預期的方式進行第一次嘗試。我也將Thread創建移出循環,並按照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--; } 

該代碼現在按預期工作。