线程安全访问列表<>只读对象

时间:2010-12-17 02:04:42

标签: c# multithreading thread-safety

我有一个对象列表,许多线程中的许多对象都可以访问这些对象。为了确保线程安全,我将列表及其对象设置为只读。我唯一关心的是List<>对象的迭代器,因为我记得读过有关迭代器线程安全问题的东西。我有问题吗?

alt text

为了澄清:在BarObservable类中,List < Bar >栏是只读的。列表中的各个条也是只读的。 MarketDataAdaptor类使用BarService向BarsObservable类添加新柱。该图未显示此信息,但IBarObservers传递了对List < Bar >的引用。他们不能写入它,但他们确实使用List的迭代器。同时更新最终栏,一旦最终确定,将在列表末尾添加一个新栏。

1 个答案:

答案 0 :(得分:2)

据我了解,您目前提供两种不变性保证:

  1. List<Bar>对象有一个不变的引用。
  2. Bar类型本身是不可变的,或者按照惯例,它的实例在添加到列表后不会发生变异。
  3. 这些都不足以处理任何并发读取器/写入器方案,因为List<T>类型本身不是线程安全的。

    1. 如果您有多个未同步的编写器,则可能会损坏列表。
    2. 如果你有一个编写器,其他线程上有读卡器,你可能不会破坏列表。另一方面,读者将无法正常工作。如果你很幸运,在写入过程中迭代列表会抛出“枚举期间更改的集合”异常。如果你不是,你的程序将默默地失去其功能正确性。
    3. 现在,您可以尝试使用锁,ReaderWriterLockSlims等同步对列表的访问。如何执行此操作将特定到您特定情况的Producer / Consumer关系。例如,您可以通过以下任一方法锁定枚举中的突变:

      1. 只要有一个活跃的不存在的枚举器,就阻止尝试变异。
      2. 每次请求枚举器时,都会阻止编写者。将列表复制到另一个列表;返回枚举器,然后取消阻止编写器。
      3. 但是,如果您使用的是.NET 4.0,我建议您查看System.Collections.Concurrent命名空间中的线程安全集合类。特别是,您可能会发现BlockingCollection<T>类正是您所需要的。

        最后,我会看一下整体设计,看看能否以无锁方式解决这个问题。