1

假设我在一个类中有一个列表,它将在多线程场景中使用。

public class MyClass
{
     List<MyItem> _list= new List<MyItem>();
     protected object SyncRoot { 
      get {
         return ((IList)_list).SyncRoot;
        }
     }

     public void Execute1()
     {
        lock(SyncRoot)
        {
             foreach(var item in _list) DoSomething(item);
        }
     }

     public void Execute2()
     {
         Item[] list;
         lock(SyncRoot)
         {
            list=_list.ToArray();
         }
           for(var i=0;i<list.Length;i++) DoSomething(list[i]);
      }
}

Execute1方法是以线程安全的方式枚举列表的“正常”方式。但是Execute2呢?这种方法仍然是线程安全的吗?

4

2 回答 2

2

在这两种情况下,对 List (副本)的访问都是线程安全的。但当然 MyItem 元素不会以任何方式同步。

第二种形式看起来有点贵,但它允许在DoSomething()s 运行时在原始形式上添加/删除。该数组就像一种快照,如果符合您的要求,它可能会很有用。请注意,您不妨使用ToList().

于 2012-04-10T07:27:54.493 回答
1

只要其他所有使用_list也受到相同lock声明的保护,它就是安全的。您正在对列表进行独占访问,复制其内容,然后处理副本(由于范围界定,您也拥有独占访问权限)。乍一看有点浪费,但在某些情况下是一种合法的方法。

于 2012-04-10T07:16:23.017 回答