3

我的问题更像是我想与其他人确认的问题,所以我确信我得到了正确的答案。当您想要进行非线程安全操作(例如枚举集合)时,最好的办法是调用 Synchronized 方法(如果该集合存在)。

例如:var syncAL = ArrayList.Synchronized( myAL );

然后你可以毫无顾虑地做一些事情:

foreach (var item in syncAL){
  // Do something
}

现在我个人并没有真正使用 ArrayLists,它只是为了示例,但是对于常规 List,Synchronized 方法不存在,所以这里的最佳做法是:

lock (list.SyncRoot){
 // non thread-safe operation, e.g:
 list.ForEach(item => Console.WriteLine(item.ToString()));
}

因为当然你可以创建你自己的任意对象,但是如果你在多个类中使用一些集合对象,你需要确保你使用同一个对象来锁定所有这些类,这似乎喜欢一种非常舒适的方式。

我想确保它确实是最佳实践,并且在添加我写的内容作为我的团队的开发技巧之前我没有遗漏任何东西:)

我对此的理解来源: MSDN SyncRoot

4

2 回答 2

4

然后你可以毫无顾虑地做一些事情:

foreach (var item in syncAL){
  // Do something
}

没有。来自MSDN

通过集合进行枚举本质上不是线程安全的过程。即使一个集合是同步的,

对于核心问题:

我想确保这确实是最佳实践

不,这是一种过时的做法。请注意,SyncRoot 仅限于ICollection,并且不支持ICollection<T>. 较新的集合 ( List<>) 不支持它,这是您的主要线索。

于 2013-04-10T21:40:19.027 回答
3

在 ArrayList.Synchronized 包装器中包装集合不会使枚举线程安全,MSDN明确指出:

...即使一个集合被同步,其他线程仍然可以修改该集合,这会导致枚举器抛出异常。

所以最好的方法仍然是锁定 SyncRoot,或者使用 System.Collections.Concurrent 命名空间中的线程安全集合。

ArrayList.Synchronized 的内部实现只会创建内部类 SyncArrayList 的实例,它将锁定 SyncRoot 以进行任何操作,如下所示:

  public override int Add(object value)
  {
    lock (this._root)
      return this._list.Add(value);
  }
于 2013-04-10T21:36:58.477 回答