List <T> .AddRange()线程安全吗?

Eri*_*bes 15 c# collections multithreading thread-safety

我可以在没有锁定的情况下从多个线程安全地调用List.AddRange(r)吗?如果没有,我会遇到什么样的麻烦?

Ian*_*ose 17

,它的文档并没有说它是线程安全的,因此它不是.

此类型的公共静态(在Visual Basic中为Shared)成员是线程安全的.任何实例成员都不保证是线程安全的.

至于可能出现的问题,请考虑AddRange(newItems)的作用:

  • 检查内部阵列中是否有足够的空间
  • 如果不:
    • 分配一个新阵列
    • 将当前项复制到新阵列
    • 将字段设置为指向新数组
  • 将newItems复制到内部数组中的正确本地
  • 更新"计数"字段(用于控制下一个项目的插入位置)

现在想想如果上面的内容与另一个对AddRange()的调用混淆,甚至只是调用读取项目会发生什么.


her*_*ter 6

不,不是,但我想补充一点,myList.AddRange(...);在锁内做一个比做几个更有效lock (syncLock) { myList.Add(...) };.

你会遇到哪种麻烦?当一个线程正在添加一个项目而另一个线程正在枚举列表时,List<T>会抛出一个异常,因为它会进行一些内部版本控制,因为它希望阻止我们糟糕的开发人员遇到令人讨厌的副作用.

另外,List<T>在内部保存在其中存储其项目的数组.也许在数组中设置一个项目是非常原子的,但是每当达到此数组的容量时,将创建一个新项目,并且将从旧项目中复制项目.因此,当一个线程想要在复制发生时添加一些东西时,你可以想象事情会不同步.