2011-08-19 68 views
2

在multhreaded .NET應用程序,.NET CLR - 對象參考同步

假設第一個線程被寫入到一個列表 第二個線程被清除所有項目在 而第三線是從列表中讀取。

如果第二個和第三個線程在CLR級別上「真正」同時訪問同一個列表對象,會發生什麼情況。我不是說.NET同步對象和鎖定機制。

我的意思是,當CLR從引用(由第3個線程)訪問列表項時),如果引用指向的列表發生變化(由第2個線程)會發生什麼?

回答

0

它爆炸了。枚舉已更改,因此拋出InvalidOperationException

+0

沒有使用激勵。考慮簡單地訪問列表中的第一項 –

+0

第二個線程仍然會爆炸。 –

2

不好的東西。

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

A List<T>可以同時支持多個閱讀器,只要該集合沒有被修改。枚舉枚舉本質上不是一個線程安全的過程。在枚舉與一個或多個寫入訪問競爭的罕見情況下,確保線程安全的唯一方法是在整個枚舉期間鎖定集合。爲了讓集合可以被多個線程讀取和寫入,您必須實現自己的同步。

0

有這麼多次失敗可能發生時,如果你傾向於更新列表,並在多線程代碼讀它,例如,假設我們有以下情形:

//c# 
List<object> myList... 

//at reading thread 
if (myList.Count > 0) 
{ 
    object item = myList[0];//get the item at the first index of the collection. 
} 

//at writing thread 
myList.Clear(); 

的寫入線程正在更新列表,同時讀取器線程正在從列表中讀取,因此假設執行如下:
讀者線程檢查集合中是否有項目,並且它發現存在一些它對它「.Count > 0是真的「,所以它繼續,但在它到達下一行之前,線程上下文切換通過切換到寫入器線程來暫停讀取器線程,因此它在此時執行其代碼myList.Clear();,線程上下文切換回到讀線程繼續執行,所以它會嘗試獲取myList[0],但收集是在這一點上由作家縷空,所以它會失敗,出現異常IndexOutOfRange ..

另一種情況是,如果讀線程哪裏扔迭代使用foreach的集合,寫入線程只是改變集合「添加/刪除」的一些項目,它會再次拋出異常,因爲集合在循環時發生了變化..

所以,你必須使用一些同步mechanizem C#中的列表,如lock交互或使用Monitor上課的時候。但是,如果你正在使用4.0,你可以關閉使用ConcurrentCollection,而不是正常的名單,它們是線程安全的集合。