2011-08-19 69 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,而不是正常的名单,它们是线程安全的集合。