在multhreaded .NET应用程序,.NET CLR - 对象参考同步
假设第一个线程被写入到一个列表 第二个线程被清除所有项目在 而第三线是从列表中读取。
如果第二个和第三个线程在CLR级别上“真正”同时访问同一个列表对象,会发生什么情况。我不是说.NET同步对象和锁定机制。
我的意思是,当CLR从引用(由第3个线程)访问列表项时),如果引用指向的列表发生变化(由第2个线程)会发生什么?
在multhreaded .NET应用程序,.NET CLR - 对象参考同步
假设第一个线程被写入到一个列表 第二个线程被清除所有项目在 而第三线是从列表中读取。
如果第二个和第三个线程在CLR级别上“真正”同时访问同一个列表对象,会发生什么情况。我不是说.NET同步对象和锁定机制。
我的意思是,当CLR从引用(由第3个线程)访问列表项时),如果引用指向的列表发生变化(由第2个线程)会发生什么?
它爆炸了。枚举已更改,因此抛出InvalidOperationException
。
不好的东西。
此类型的公共静态(Visual Basic中的Shared)成员是线程安全的。 任何实例成员不保证是线程安全的。
A
List<T>
可以同时支持多个阅读器,只要该集合没有被修改。枚举枚举本质上不是一个线程安全的过程。在枚举与一个或多个写入访问竞争的罕见情况下,确保线程安全的唯一方法是在整个枚举期间锁定集合。为了让集合可以被多个线程读取和写入,您必须实现自己的同步。
有这么多次失败可能发生时,如果你倾向于更新列表,并在多线程代码读它,例如,假设我们有以下情形:
//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
,而不是正常的名单,它们是线程安全的集合。
没有使用激励。考虑简单地访问列表中的第一项 –
第二个线程仍然会爆炸。 –