为什么使用 ImmutableList 而不是 ReadOnlyCollection?
Why use ImmutableList over ReadOnlyCollection?
.NET 4.5 有一个新的命名空间 System.Collections.Immutable
This package provides collections that are thread safe and guaranteed to never change their contents, also known as immutable collections.
我很困惑。 ReadOnlyCollection class? Why use ImmutableList 不是已经解决了线程安全问题吗?
我知道还有一个 IReadOnlyList interface。这并没有隐含地解决线程安全问题,因为其他线程可能会通过另一个接口编辑该对象。
A collection that is read-only is simply a collection with a wrapper
that prevents modifying the collection; therefore, if changes are made
to the underlying collection, the read-only collection reflects those
changes.
ImmutableList
不会发生这种情况。
ReadOnlyCollection
,顾名思义,只能读
另一方面,您可以通过调用 Add
/Remove
/Clear
方法 append/remove 项 to/from 和 ImmutableList
,例如,其中 return 一个新的不可变列表。
ReadOnlyCollection<T>
没有解决任何线程安全问题。它只是 Ilist<T>
的包装。它不会公开修改集合的成员,但您始终可以使用底层集合引用修改它。
如果基础集合被修改,枚举 ReadOnlyCollection<T>
是不安全的。如果这样做,您将获得与消息 "Collection was modified; enumeration operation may not execute...".
相同的 InvalidOperationException
A ReadOnlyCollection can support multiple readers concurrently, as
long as the collection is not modified. Even so, enumerating through a
collection is intrinsically not a thread-safe procedure. To guarantee
thread safety during enumeration, you can lock the collection during
the entire enumeration. To allow the collection to be accessed by
multiple threads for reading and writing, you must implement your own
synchronization.
另一方面,ImmutableList
是不可变的,因此本质上是线程安全的。
在 multi-threaded 场景中,请注意 read-only 集合仍然不是 thread-safe。
来自 ReadOnlyCollection<T>
文档:
... if changes are made to the underlying collection, the read-only collection reflects those changes
由于集合,如 List<T>
和其他集合,不是线程安全的,因此 read-only 集合也不是线程安全的。
重要提示:有些特殊情况您不会在 MSDN 中找到明确解释。一些看似只读取集合内容的操作,实际上是在修改集合的内部结构。为什么没有指定? - 一个明显的原因是因为这是一个没有反映在 API 上的实现细节。结果是,即使你不修改包裹在ReadOnlyCollection<T>
中的List<T>
,只使用getter,在multi-threaded环境中仍然会发生崩溃!
底线是通用集合,即使包装在 ReadOnlyCollection
中也不能开箱即用地用于 multi-threaded 环境。
与ReadOnlyCollection
相反,不可变集合确实保证 none 的内部结构在获得对集合的引用后将永远改变。请注意,这些结构仍然不是真正不可变的。相反,它们 可冻结 。这意味着该结构将在内部更改一段时间,直到它被 frozen 并返回给调用者。除此之外,对不可变集合的所有其他调用只会在可通过原始引用访问的结构之外进行修改。
结论:Read-only 集合不是 thread-safe;不可变集合是 thread-safe.
.NET 4.5 有一个新的命名空间 System.Collections.Immutable
This package provides collections that are thread safe and guaranteed to never change their contents, also known as immutable collections.
我很困惑。 ReadOnlyCollection class? Why use ImmutableList 不是已经解决了线程安全问题吗?
我知道还有一个 IReadOnlyList interface。这并没有隐含地解决线程安全问题,因为其他线程可能会通过另一个接口编辑该对象。
A collection that is read-only is simply a collection with a wrapper that prevents modifying the collection; therefore, if changes are made to the underlying collection, the read-only collection reflects those changes.
ImmutableList
不会发生这种情况。
ReadOnlyCollection
,顾名思义,只能读
另一方面,您可以通过调用 Add
/Remove
/Clear
方法 append/remove 项 to/from 和 ImmutableList
,例如,其中 return 一个新的不可变列表。
ReadOnlyCollection<T>
没有解决任何线程安全问题。它只是 Ilist<T>
的包装。它不会公开修改集合的成员,但您始终可以使用底层集合引用修改它。
如果基础集合被修改,枚举 ReadOnlyCollection<T>
是不安全的。如果这样做,您将获得与消息 "Collection was modified; enumeration operation may not execute...".
InvalidOperationException
另一方面,A ReadOnlyCollection can support multiple readers concurrently, as long as the collection is not modified. Even so, enumerating through a collection is intrinsically not a thread-safe procedure. To guarantee thread safety during enumeration, you can lock the collection during the entire enumeration. To allow the collection to be accessed by multiple threads for reading and writing, you must implement your own synchronization.
ImmutableList
是不可变的,因此本质上是线程安全的。
在 multi-threaded 场景中,请注意 read-only 集合仍然不是 thread-safe。
来自 ReadOnlyCollection<T>
文档:
... if changes are made to the underlying collection, the read-only collection reflects those changes
由于集合,如 List<T>
和其他集合,不是线程安全的,因此 read-only 集合也不是线程安全的。
重要提示:有些特殊情况您不会在 MSDN 中找到明确解释。一些看似只读取集合内容的操作,实际上是在修改集合的内部结构。为什么没有指定? - 一个明显的原因是因为这是一个没有反映在 API 上的实现细节。结果是,即使你不修改包裹在ReadOnlyCollection<T>
中的List<T>
,只使用getter,在multi-threaded环境中仍然会发生崩溃!
底线是通用集合,即使包装在 ReadOnlyCollection
中也不能开箱即用地用于 multi-threaded 环境。
与ReadOnlyCollection
相反,不可变集合确实保证 none 的内部结构在获得对集合的引用后将永远改变。请注意,这些结构仍然不是真正不可变的。相反,它们 可冻结 。这意味着该结构将在内部更改一段时间,直到它被 frozen 并返回给调用者。除此之外,对不可变集合的所有其他调用只会在可通过原始引用访问的结构之外进行修改。
结论:Read-only 集合不是 thread-safe;不可变集合是 thread-safe.