2013-01-25 70 views
3
for (int i = 0; i < 10; i++) 
    new Thread (() => Console.Write (i)).Start(); 

正如預期的那樣,上面的代碼的輸出是不確定的,因爲變量i是指相同的存儲器位置在整個循環的壽命。因此,每個線程,因爲它正在運行傳遞數據到使用lambda線程表達式

然而,

for (int i = 0; i < 10; i++) 
{ 
    int temp = i; 
    new Thread (() => Console.Write (temp)).Start(); 
} 

還正在非確定性輸出上,其值可以改變一個變量調用Console.Write!我認爲每個循環迭代的變量temp都是局部的。因此,每個線程都捕獲了不同的內存位置,應該有np問題。

+2

輸出的非確定性性質是什麼? – phoog

+1

第二個版本應該可以工作 - Eric Lippert在這裏發表了關於閉環變量的閉包:http://blogs.msdn.com/b/ericlippert/archive/2009/11/12/closing-over-the-loop-variable-considered -harmful.aspx – Paolo

+1

它不應該是「確定性的」,因爲「線程調度的順序總是相同的」。也許這就是問題的含義? –

回答

2

你的程序應該有10個lambda表達式,每個表達一個從0到9的數字到控制檯。但是,不能保證線程將按順序執行。

+2

OP代碼中沒有換行符,所以所有的數字都將在唯一的行中。 – AgentFire

+0

@AgentFire啊,我明白了。我看到只有「Write」的「WriteLine」。我已經編輯了一些答案。 – phoog

+0

Console.Write()*是*線程安全的,因爲寫入它的整個字符串將永遠不會*交錯字符。 –

1

代碼片段應該是確定性的,因爲每個線程最終都會寫入它的temp,並且它們的所有臨時數據都會有所不同。

但是,它並不保證線程將按照其創建順序進行安排。你會看到所有可能的臨時表,但不一定按升序排列。

2

也給予非確定性輸出!

不,它不是。我檢查過你的第一個代碼(有重複數字)十次,第二個(沒有)。

所以一切正常。正如它應該的那樣。

+0

不,它不。添加隨機睡眠,你會看到。 –

1

這是證明OP是正確的,他的兩段代碼都是不正確的。

而且還有一個解決方案與證明也。

但是需要注意的是「不確定性」是指線程收到錯誤的參數訂單將是從來沒有保證。

下面的代碼檢查第二片的OP代碼,並表明它正在按預期..

我存儲所述一組(線程標識,參數),然後將其打印與線程輸出到比較證明對沒有改變。我還增加了幾百毫秒的隨機睡眠,因此索引應該在那些時候明顯改變。

 Dictionary<int, int> hash = new Dictionary<int, int>(); 
     Random r = new Random(DateTime.Now.Millisecond); 
     for (int i = 0; i < 10; i++) 
     { 
      int temp = i; 
      var th = new Thread(() => 
      { 
       Thread.Sleep(r.Next(9) * 100); 
       Console.WriteLine("{0} {1}", 
        Thread.CurrentThread.GetHashCode(), temp); 
      }); 

      hash.Add(th.GetHashCode(), temp); 

      th.Start(); 
     } 

     Thread.Sleep(1000); 
     Console.WriteLine(); 

     foreach (var kvp in hash) 
      Console.WriteLine("{0} {1}", kvp.Key, kvp.Value);