访问 List<> 的线程安全只读对象的数量

发布于 2024-10-08 01:17:24 字数 485 浏览 0 评论 0 原文

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

alt text

澄清一下:在 BarObservable 类中, List 栏>栏是只读的。列表中的各个栏也是只读的。 MarketDataAdaptor 类使用 BarService 将新柱添加到 BarsObservable 类中。该图没有显示这一点,但 IBarObservers 被传递了对 List List 栏>。他们无法写入它,但他们确实使用列表的迭代器。同时,最终的栏会更新,一旦完成,新的栏就会添加到列表的末尾。

I have a list of objects which will be accessible by many objects across many threads. To ensure thread safety I have made the list and its object read-only. My only concern is the iterators of the List<> object because I remember reading something about iterator thread safety issues. Do I have a problem?

alt text

For clarification: in the BarObservable class, the List < Bar > bar is read-only. The individual bars of the list are also read-only. The MarketDataAdaptor class uses BarService to add new bars to BarsObservable class. The diagram doesn't show this but the IBarObservers are passed a reference to the List < Bar > . They can't write to it but they do use the iterator of the List. Meanwhile the final bar is updated and once finalized a new bar is added to the end of the list.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

路还长,别太狂 2024-10-15 01:17:24

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

  1. 存在对 List 对象的不变引用。
  2. Bar 类型本身是不可变的,或者按照惯例,它的实例在添加到列表后不会发生变化。

这些都不足以处理任何并发读取器/写入器场景,因为 List 类型本身不是线程安全的。

  1. 如果您有多个不同步的编写器,则可能会损坏列表。
  2. 如果您只有一个写入器,而读取器位于其他线程上,则可能不会损坏该列表。另一方面,读者将无法正常工作。如果幸运的话,在写入过程中迭代列表将引发“枚举期间集合已更改”异常。如果你不这样做,你的程序将默默地失去其功能的正确性。

现在,您可以尝试使用锁、ReaderWriterLockSlims 等同步对列表的访问。您的具体操作方式将特定取决于您特定情况的生产者​​/消费者关系。例如,您可以通过以下任一方式在枚举期间锁定突变:

  1. 只要存在活动的未处置枚举器,就阻止突变尝试。
  2. 每次请求枚举器时,都会阻止写入器。将列表复制到另一个列表;返回其枚举器,然后取消阻止写入者。

但我建议,如果您使用 .NET 4.0,请查看 System.Collections.Concurrent 命名空间。特别是,您可能会发现BlockingCollection 类正是您所需要的。

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

As I understand it, you currently provide two immutability guarantees:

  1. There is an unchanging reference(s) to a List<Bar> object.
  2. The Bar type itself is immutable or is, by convention, instances of it are not mutated after they are added to the list.

Neither of these is sufficient to deal with any concurrent reader / writer scenarios since the List<T> type itself is not thread-safe.

  1. If you have multiple unsynchronized writers, you could corrupt the list.
  2. If you have a single writer, with reader(s) on other threads, you probably won't corrupt the list. On the other hand, the readers won't work correctly. If you're lucky, iterating the list in the middle of a write will throw a "Collection changed during enumeration" exception. If you're not, your program will silently lose its functional correctness.

Now you could try synchronizing access to the list with locks, ReaderWriterLockSlims, etc. How you do this will be specific to the Producer / Consumer relationships of your particular situation. For example, you could lock mutation during enumeration by either of these:

  1. Hold up an attempt to mutate as long as there is an active undisposed enumerator.
  2. Every time an enumerator is requested, block writers. Copy the list to another list; return its enumerator, and then unblock writers.

But I would suggest, if you are on .NET 4.0, to take a look at the thread-safe collection classes in the System.Collections.Concurrent namespace. In particular, you may find the BlockingCollection<T> class to be exactly what you need.

Finally, I would look at the overall design to see if you can solve this problem in a lock-free manner.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文