C#处理集合时线程安全的最佳实践(已经不是并发的)
我的问题更像是我想和其他人确认的东西,所以我确信我得到了正确的答案。 当您想要执行非线程安全的操作(例如对集合进行枚举)时,最好是调用Synchronized方法(如果该集合存在) e、 g:C#处理集合时线程安全的最佳实践(已经不是并发的),c#,multithreading,collections,synchronization,thread-safety,C#,Multithreading,Collections,Synchronization,Thread Safety,我的问题更像是我想和其他人确认的东西,所以我确信我得到了正确的答案。 当您想要执行非线程安全的操作(例如对集合进行枚举)时,最好是调用Synchronized方法(如果该集合存在) e、 g:var syncAL=ArrayList.Synchronized(myAL) 然后你就可以无忧无虑地做一些事情: foreach (var item in syncAL){ // Do something } 现在我个人并不真正使用ArrayList,这只是一个示例,但对于常规列表,Synchron
var syncAL=ArrayList.Synchronized(myAL)代码>
然后你就可以无忧无虑地做一些事情:
foreach (var item in syncAL){
// Do something
}
现在我个人并不真正使用ArrayList,这只是一个示例,但对于常规列表,Synchronized方法并不存在,因此这里的最佳实践是:
lock (list.SyncRoot){
// non thread-safe operation, e.g:
list.ForEach(item => Console.WriteLine(item.ToString()));
}
当然,您可以创建自己的任意对象,但是如果您在多个类中使用某个集合对象,您需要确保在所有这些类中使用相同的对象进行锁定,这似乎是一种非常舒适的方法
我想确保这是一个真正的最佳实践,在我为我的团队添加开发技巧之前,我没有遗漏任何东西:)
我对此的理解来源:
在ArrayList中包装集合。同步包装不会使枚举线程安全,明确声明:
…即使在同步集合时,其他线程仍可以修改该集合,这会导致枚举数引发异常
所以最好的方法仍然是锁定SyncRoot,或者使用System.collections.Concurrent命名空间中的线程安全集合
ArrayList.Synchronized的内部实现只会创建内部类SyncArrayList的实例,它会为任何操作锁定SyncRoot,如下所示:
public override int Add(object value)
{
lock (this._root)
return this._list.Add(value);
}
然后你就可以无忧无虑地做一些事情:
foreach (var item in syncAL){
// Do something
}
编号:发件人:
通过集合枚举本质上不是线程安全的过程。即使集合已同步
至于核心问题:
我想确保这确实是最好的做法
不,这是一种过时的做法。请注意,SyncRoot仅限于ICollection
,而ICollection
不支持它。较新的集合(List
)不支持它,这是您的主要线索 谢谢你的快速回答