ReadOnlyCollection <T>线程安全

M.A*_*nin 9 .net concurrency multithreading immutability thread-safety

ReadOnlyCollection(T)的文档指出:

A ReadOnlyCollection(Of T)只要不修改集合,就可以同时支持多个读者.即便如此,通过集合枚举本质上不是一个线程安全的过程.为了在枚举期间保证线程安全,您可以在整个枚举期间锁定集合.要允许多个线程访问集合以进行读写,您必须实现自己的同步.

我的问题是关于粗体部分:

  1. 为什么枚举通过一个本质上不是线程安全的集合
  2. 有什么可能的影响,和
  3. 什么是常用的解决方法?

Mik*_*kis 8

C#有一个非常好的集合模型,但ReadOnlyCollection类是整个模型中最不幸的构思(或命名)类之一.它应该更恰当地称为只读列表,而不是只读集合.

现在,为了解决您的问题,它只是在构造时提供的IList的只读装饰器.因此,构造ReadOnlyCollection的代码可以修改原始列表,其中包含这将对多线程访问产生的所有后果.

因此,如果集合是真正的只读,那么通过集合枚举将是线程安全的; 但由于它不是只读的,因此它不是线程安全的.鉴于您拥有的声誉,我很确定您不会想知道为什么通过非只读集合进行枚举不是线程安全的.

至于你问的解决方法,你可以使用锁定,或者你可以使用lock-nothing(或尽可能少的锁定)原则并制作列表的真正只读副本.

编辑

几个月后我重新阅读了我的答案,(感谢asyncwait的评论),我意识到我应该回答所有OP的问题而不根据他的声誉做出假设.OP现在可能已收到他的回答,但我会为了未来的读者而这样做.

枚举非真正只读集合本质上不是线程安全的,原因相同,即使在单线程场景中,您也无法在枚举时修改集合.(Java中的ConcurrentModificationException,C#中的InvalidOperationException.)在单线程场景中,您可以确保您的枚举代码不会以任何方式尝试更改集合,但在多线程场景中,一个线程可能正在枚举集合另一个线程可能正在同时改变它.