2011-04-16 61 views
0

我正在學習C#,目前正在學習線程。Interlocked.increment仍然沒有解決價值缺失問題

下面是一個簡單的例子來加1,不同的線程內的可變多次。

本書建議我可以使用Interlocked.increment(ref number)替換AddOne方法中的+= 1,因此該值將被鎖定,直到它在線程中更新爲止。如預期的那樣,輸出將是1000, 2000, ..... 10000。但我的輸出仍然是999, 1999, 2999, ...... 9999

後,才取消對Thread.Sleep(1000)線將輸出是正確的,但即使沒有被使用Interlocked

誰能解釋這裏發生了什麼?

static void Main(string[] args) 
{ 
    myNum n = new myNum(); 

    for (int i = 0;i<10; Interlocked.Increment(ref i)) 
    { 
     for(int a =1;a<=1000; Interlocked.Increment(ref a)) 
     { 
      Thread t = new Thread(new ThreadStart(n.AddOne)); 
      t.Start(); 
     } 

     //Thread.Sleep(1000); 
     Console.WriteLine(n.number); 
    } 
} 

class myNum 
{    
    public int number = 0; 

    public void AddOne() 
    { 
     //number += 1; 
     Interlocked.Increment(ref number); 
    } 
} 

回答

0

這有點怪我你想實現這個代碼是什麼。您在任何地方都使用Interlocked.Increment,但沒有明確的需求。

Interlocked.Increment需要訪問值可以從不同的線程進行訪問。在你的代碼是唯一number,所以你不需要它ia,只是用作爲一般i++a++

你問的問題是,你只是不等待您發表的所有主題完成了它的工作。看看Thread.Join()方法。您必須等待全部您開始的線程完成其工作。

在這個簡單的測試中,你完成了Thread.Sleep(1000);你做類似的等待,但它不正確,假設所有線程都在1000毫秒內完成,所以只需使用Thread.Join()

如果您修改AddOne()方法以使其開始執行更長時間(例如,將Thread.Sleep(1000)添加到該方法中),您會注意到Thread.Sleep(1000);對此沒有任何幫助。

我會建議閱讀更多關於ThreadPool vs Threads。也看看Patterns for Parallel Programming: Understanding and Applying Parallel Patterns with the .NET Framework 4

+0

實際上,Thread.Sleep(1000)仍然可以正常工作,如果您在AddOne()中執行Thread.Sleep(10),因爲10 << 1000. – Fantius 2011-04-17 00:09:02

+0

感謝您的所有答案,使用for循環中的Interlocked.Increment是書中的示例代碼,我認爲這不是必需的。它等待線程才能完成,非常有用。我會按照你的建議做更多的閱讀。乾杯! – user711657 2011-04-17 00:17:23

+0

@Fantius,這取決於,因爲一次啓動10000個線程可能會壓倒系統,但實際上你在大多數現代系統上都是正確的,它幾乎不明顯。我會更正,謝謝。 – 2011-04-17 00:21:32

4

在所有線程完成執行之前,您正在打印出該值。打印前您需要加入所有線程。

for(int a = 0; a < 1000; a++) 
    { 
    t[a].Join(); 
    } 

您需要將線程存儲在數組或列表中。另外,在任何for循環中都不需要互鎖指令。它們都只在一個線程中運行(主線程)。只有AddOne中的代碼在多個線程中運行,因此需要通過同步。

相關問題