2012-11-19 36 views
2

我有兩個獨立的任務和兩個獨立的操作。我認爲t0是線程安全的,但我不確定t1。這是對的嗎?併發字典的性能很糟糕,我需要向集合中插入大量數據。c中的並行任務和線程安全#

var t0 = new Task[2] 
{ 
    Task.Factory.StartNew(()=> 
    { 
     list1=new sortedlist<int,int>(sortedlist1) 
    } 
    }), 
    Task.Factory.StartNew(()=> 
    { 
     list2=new sortedlist<int,int>(sortedlist2) 
    }) 
}; 
Task.WaitAll(t0) 

var t1 = new Task[2] 
{ 
    Task.Factory.StartNew(()=> 
    { 
     foreach (var item in sortedlist1) 
     { 
      list1.Add(item.Key, item.Value); 
     } 
    }), 
    Task.Factory.StartNew(()=> 
    { 
     foreach (var item in sortedlist2) 
     { 
      list2.Add(item.Key, item.Value); 
     } 
    }) 
}; 
Task.WaitAll(t1) 
+0

任務之間似乎沒有什麼共同之處。你爲什麼認爲它不是線程安全的? –

+0

準確地說,我很驚訝,因爲在t0沒有數據丟失,但在t1的一部分我的數據丟失 – mohammad

+0

這是一個http://codereview.stackexchange.com類問題 – Alex

回答

0

這看起來沒問題 - 你沒有在任務中訪問同一個變量。 t1 []中的任務在t0 []中的任務完成之前不會運行。

您可以使用Parallel.Do()而不是在數組中創建任務,然後等待它們完成 - 這會讓您的意圖更加清晰,並避免大量的基於陣列的儀式。

我假設你已經組成了一個例子,而不是實際的代碼?

+0

我在靜態方法中編寫了這段代碼,它返回一個包含2個排序列表的類變量。 – mohammad

1

正如所寫,此代碼不起作用。第一對任務中分配的列表未分配給第二對任務使用的變量。讓我們忽略它,只是看一下這裏的一般概念。

這兩個列表不必在單獨的線程中分配以用於單獨的線程。而且你絕對不需要浪費在單獨任務中分配每個列表的工作。這些列表可以由主線程分配,特別是如果主線程想在任務完成後使用列表。唯一真正的問題是是否有可能同時由兩個線程修改一個列表。

如果list1只能被task1讀寫,而list2只能被task2讀寫,那麼你可以在它們各自的任務中做任何你想要的列表而沒有任何衝突。

使用Task.WaitAll,因爲您已經在等待兩個任務完成。兩項任務完成後,主線程可以控制list1和list2以進行進一步的修改。在一組並行執行的任務之後的一個常見後續操作是將多個任務的工作合併爲最終輸出。 (請參閱「MapReduce」)

+0

儘管t1中的兩個操作是獨立的,但在第二個任務中錯過了數據 – mohammad

+0

根據這個解釋,您認爲多任務在這種情況下沒有用處,我應該使用順序編程。因爲我想如果我使用多任務來填充列表,速度會增加 – mohammad

+0

我說多任務並不是分配列表對象所必需的。將list.add()並行執行到多個獨立列表可能有價值。完成之後,您有N個任務的N個列表。那又怎麼樣?當你需要在列表中找到某些東西時,你是否打算執行N次查找?可能不會。常見模式是在完成所有任務後將多個任務的輸出合併到一個列表中。這是「mapreduce」模式。 – dthorpe