2013-01-20 50 views
3

因此,它在C#中,基本上我會有一個數組中的位置爲每個線程存儲一些數據。我需要鎖定嗎?例如:多個線程寫入陣列

int[] threads = new int[12]; 

每個線程將訪問陣列例如在一個特定的位置時,線程1將更新線程的值[0],線程2個線程[1],等等

思想是讓控制檯打印存儲在數組中的值。

好吧有這麼多評論。我想我會澄清我在做什麼,希望我會學到更多。所以基本上它的要點是:

主線程啓動12個獨立的線程,每個線程在主線程中調用一個函數來從數據庫中獲取一堆記錄。對該方法的訪問被鎖定,但它返回大約100條記錄供線程自行處理。

當線程正在處理記錄時,它會發出幾個Web請求並插入到數據庫中。一旦線程完成了一批記錄的處理,它就會再次從主線程調用一個函數,並且該函數將啓動一個新線程來代替最後一個正在完成的線程。

由於線程正在做他們的處理,我想在控制檯中輸出他們的進度。最初我鎖定了每個控制檯的輸出,因爲如果同時調用同一個函數,每個輸出的光標位置將遍佈整個地方。所以我想我會有一個數組存儲每個值的計數,然後有一個函數將它全部打印出來。儘管我開始懷疑這是否與我目前所做的完全不同。

+2

請注意,由於[錯誤分享](https://en.wikipedia.org/wiki/False_sharing),這可能是無效的。除非你非常清楚**你正在做什麼,否則將多個線程寫入通用對象(併發集合除外)永遠不是一個好主意。你應該重構你的程序流程,這樣就沒有必要。 –

+0

我非常同意@KonradRudolph在這裏 - [見我給另一個SO的答案](http://stackoverflow.com/questions/12390468/multithreading-slower-than-singlethreading/12390662#12390662)OP描述的情況其中多線程應用程序比單線程版本慢(包括一個非常好的鏈接到一個優秀的MSDN文章)。我這樣做並不是爲了獲得新答案 - 但是因爲這是一個很少被人理解的現象,人們越多越好:) –

+2

這些傢伙是對的。這聞起來很可怕。記住,你應該像對待員工那樣對待線索:他們很貴,所以不要僱用他們,除非你有很多工作要做。那些線程將大部分時間都閒置,等待數據庫。如果你期待12封信,你會僱用12位祕書在郵箱旁等待嗎?除非他們使你的處理器達到最大化,否則不要創建線程,也不要製造比處理器更多的線程。 –

回答

2

我相信如果每個線程只在數組的一個單獨部分工作,一切都會好的。如果您要共享數據(即在線程之間進行通信),那麼您需要某種內存屏障來避免內存模型問題。

我相信如果你產生了一堆線程,每一個線程都填充它自己的數組部分,那麼等待所有這些線程完成使用Thread.Join,這將爲你做到足夠的障礙注意安全。

MSDN documentation on Arrays說:

公共靜態(在Visual Basic中的Shared)這種類型的 成員都是線程安全的。 任何實例成員不是 保證是線程安全的。

此實現不提供 同步(線程安全)包裝 數組;但是,基於Array的.NET Framework 類使用SyncRoot 屬性提供了 自己的同步版本 集合。

枚舉整個集合是 本質上不是線程安全的 過程。即使集合是 同步,其他線程仍可以 修改集合,這會導致枚舉器引發 引發異常。 要在枚舉中保證線程安全,您可以在整個 枚舉期間鎖定 集合,或者捕獲由其他 線程所做更改產生的異常 。

所以不,他們不是線程安全的。通常,當併發訪問可能在內部失敗時,集合被認爲是「不是線程安全的」,但是由於每個線程將訪問不同的位置,因此這裏沒有併發訪問。

4

如果每個線程都在自己的索引處訪問一個值,那麼您應該沒問題,因爲您不必擔心同時從多個線程進行訪問。

+1

這應該也是我的回答,雖然它仍然是一個災難的食譜:) – slugster

+1

請詳細說明食譜災難.. – sridawg

+0

@sridawg - 這是一個災難的食譜,因爲在某個地方,你可能訪問多個結構線程...在這種情況下,事情不再是線程安全的。 –