2015-09-05 58 views
3

我有以下代碼,其中兩個線程正在列表中添加新元素。下面的代碼是如何自動線程安全的?

public class Numbers 
     { 
      public int number; 
      public string threadName; 
     } 
     static void Main(string[] args) 
     { 

      List<Numbers> numbers = new List<Numbers>(); 

      Task t = Task.Factory.StartNew(() => { 
       for (int i = 0; i < 999; i++) 
       { 
        numbers.Add(new Numbers() { number = i, threadName = "t" }); 

       } 
      }); 
      Task k = Task.Factory.StartNew(() => 
      { 
       for (int i = 0; i < 999; i++) 
       { 
        numbers.Add(new Numbers() { number = i, threadName = "k" }); 
       } 
      }); 


      t.Wait(); 
      k.Wait(); 


      StreamWriter writer = new StreamWriter("text.txt"); 

      foreach (var item in numbers) 
      { 
       writer.WriteLine(item.threadName + item.number); 
      } 
      writer.Flush(); 
      Console.WriteLine("Done!"); 
      Console.ReadLine(); 
     } 

當我打開文本文件,我看到他們完全對齊從k0k1 ... k999t0t1 ... t999。但是我期待這份清單能夠混合或混洗。爲什麼這兩項任務不是以隨機方式添加新元素,而是完全排序?

+0

可能是因爲你的任務很快完成了,第一個完成之前就完成了第二個任務?不是'List '無論如何都不是線程安全的,所以只要你讓兩個任務真正並行運行,你就會從Add()拋出異常。 – CodeCaster

+0

@CodeCaster你永遠是對的。添加元素後,我添加了一個小線程睡眠,是的,他們是不可預知的。 – ozgur

回答

2

您的任務絕對不是線程安全的,因爲它們正在同時寫入同一個列表。您看到的結果最可能的原因是第一項任務快速完成 - 在第二項任務有機會開始之前完成所有999個對象的寫入。

如果您爲任務的執行添加一個隨機的短延遲,您將看到結果的一些隨機性。讓你的任務做更多的工作也可能會增加一些隨機性:例如,如果你將你的列表設爲List<string>並且隨時構建你的字符串,那麼第二個任務可能會在第一個任務完成之前開始。

+0

任務'k'永遠不會執行,直到't'完成。 –

+1

@ M.kazem我不這麼認爲。 'Task.Factory.StartNew()'立即啓動任務。 Wait()就在那裏,所以代碼只有在兩個任務完成後才繼續。 – CodeCaster

+0

@ M.kazemAkhgary它肯定會開始,並可能實際完成。 (['TaskFactory.StartNew'文檔](https://msdn.microsoft.com/en-us/library/dd321439%28v=vs.110%29.aspx?f=255&MSPPError=-2147217396))。 – dasblinkenlight