2010-12-17 74 views
1

我有许多对象的列表,许多对象可以通过多个线程访问它。为确保线程安全,我已将列表及其对象设置为只读。我唯一担心的是List<>对象的迭代器,因为我记得阅读了关于迭代器线程安全问题的一些内容。我有问题吗?访问只读对象列表<>的线程安全

alt text

为了澄清:在BarObservable类中,List < Bar >栏为只读。列表中的单个条也是只读的。 MarketDataAdaptor类使用BarService向BarsObservable类添加新条。该图不显示此内容,但IBarObservers通过对List < Bar >的引用。他们不能写入,但他们确实使用List的迭代器。与此同时,最终的酒吧更新,并且一旦最终完成,新的酒吧将被添加到列表的末尾。

+1

该列表在最初填充后是否会发生变化? – Ani 2010-12-17 02:07:05

+0

是的。它的名单不断由内部班级更新。 – bkarj 2010-12-17 02:07:52

+4

然后答案是否定的。如果你在.NET 4上,我建议你看看System.Collections.Concurrent命名空间。 http://msdn.microsoft.com/en-us/library/system.collections.concurrent.aspx – Ani 2010-12-17 02:09:25

回答

2

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

  1. 有一个不变的参考文献中的List<Bar>对象。
  2. Bar类型本身是不可变的,或者按照惯例,它的实例在它们被添加到列表后不会发生变化。

这些都不是足够的,因为List<T>本身不是线程安全的,以应付任何并行读/写器的情况。

  1. 如果您有多个未同步的作者,可能会损坏列表。
  2. 如果您有一个作家,并在其他线程上有阅读器,您可能不会损坏列表。另一方面,读者将无法正常工作。如果幸运的话,在写入过程中迭代列表将抛出“在枚举期间更改集合”异常。如果你不是,你的程序将默默地失去其功能的正确性。现在

你可以尝试与同步锁,ReaderWriterLockSlims等访问列表,你怎么做这将是具体到你的特殊情况的生产者​​/消费者的关系。例如,您可以通过以下任一方法在枚举过程中锁定突变:

  1. 只要存在活动的未处理枚举数,就试图进行变异。
  2. 每次请求枚举器时,都会阻止写入者。将列表复制到另一个列表;返回枚举器,然后解锁编剧。

但是我建议,如果你使用的是.NET 4.0,可以看看System.Collections.Concurrent命名空间中线程安全的集合类。特别是,您可能会发现BlockingCollection<T>类正是您所需要的。

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