以线程安全的方式枚举列表

本文关键字:枚举 列表 方式 线程 安全 | 更新日期: 2023-09-27 18:30:47

假设我在一个类中有一个列表,它将用于多线程方案。

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 呢?这种方法是否仍然是线程安全的?

以线程安全的方式枚举列表

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

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

只要

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