ConcurrentBag比List好吗?

时间:2022-11-07 13:50:00

I am using a Parallel.Foreach for populating an external ConcurrentBag. I tried also to use a common List and everything works fine.

我使用Parallel.Foreach来填充外部ConcurrentBag。我也尝试使用一个常见的List,一切正常。

I have been lucky or I missed the special scope of ConcurrentBag?

我很幸运或者我错过了ConcurrentBag的特殊范围?

3 个解决方案

#1


18  

You have been lucky; Parallel.ForEach to populate a List is not thread-safe, you will eventually run into problems.

你很幸运; Parallel.ForEach填充List不是线程安全的,最终会遇到问题。

According to MSDN, List<T> is not thread safe:

根据MSDN,List 不是线程安全的:

Any instance members are not guaranteed to be thread safe.

任何实例成员都不保证是线程安全的。

A List<T> can support multiple readers concurrently, as long as the collection is not modified. Enumerating through a collection is intrinsically not a thread-safe procedure. In the rare case where an enumeration contends with one or more write accesses, the only way to ensure thread safety is to 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.

List 可以同时支持多个读者,只要不修改集合即可。枚举集合本质上不是线程安全的过程。在枚举与一个或多个写访问争用的极少数情况下,确保线程安全的唯一方法是在整个枚举期间锁定集合。要允许多个线程访问集合以进行读取和写入,您必须实现自己的同步。

ConcurrentBag is what you should use for this, which is thread-safe for multiple readers and writers.

ConcurrentBag是你应该使用的,这对多个读者和编写者来说是线程安全的。

#2


5  

If you're using Parallel.ForEach to populate a List<T> and everything is working just fine then you're simply getting lucky. The ForEach method can and will run your code on multiple threads so any communication outside the ForEach must be with objects that can handle concurrent updates. List<T> cannot but ConcurrentBag<T> can.

如果你使用Parallel.ForEach来填充List 并且一切正常,那么你就是幸运的。 ForEach方法可以并且将在多个线程上运行您的代码,因此ForEach之外的任何通信必须与可以处理并发更新的对象一起。 List 不能,但ConcurrentBag 可以。

#3


2  

ConcurrentBag is the correct answer, only in .NET 4.0 it is very slow. This has been fixed in .NET 4.5. See http://ayende.com/blog/156097/the-high-cost-of-concurrentbag-in-net-4-0

ConcurrentBag是正确答案,仅在.NET 4.0中它非常慢。这已在.NET 4.5中修复。见http://ayende.com/blog/156097/the-high-cost-of-concurrentbag-in-net-4-0

Both ConcurrentStack and ConcurrentQueue will also work in your situation...

ConcurrentStack和ConcurrentQueue也适用于您的情况......

#1


18  

You have been lucky; Parallel.ForEach to populate a List is not thread-safe, you will eventually run into problems.

你很幸运; Parallel.ForEach填充List不是线程安全的,最终会遇到问题。

According to MSDN, List<T> is not thread safe:

根据MSDN,List 不是线程安全的:

Any instance members are not guaranteed to be thread safe.

任何实例成员都不保证是线程安全的。

A List<T> can support multiple readers concurrently, as long as the collection is not modified. Enumerating through a collection is intrinsically not a thread-safe procedure. In the rare case where an enumeration contends with one or more write accesses, the only way to ensure thread safety is to 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.

List 可以同时支持多个读者,只要不修改集合即可。枚举集合本质上不是线程安全的过程。在枚举与一个或多个写访问争用的极少数情况下,确保线程安全的唯一方法是在整个枚举期间锁定集合。要允许多个线程访问集合以进行读取和写入,您必须实现自己的同步。

ConcurrentBag is what you should use for this, which is thread-safe for multiple readers and writers.

ConcurrentBag是你应该使用的,这对多个读者和编写者来说是线程安全的。

#2


5  

If you're using Parallel.ForEach to populate a List<T> and everything is working just fine then you're simply getting lucky. The ForEach method can and will run your code on multiple threads so any communication outside the ForEach must be with objects that can handle concurrent updates. List<T> cannot but ConcurrentBag<T> can.

如果你使用Parallel.ForEach来填充List 并且一切正常,那么你就是幸运的。 ForEach方法可以并且将在多个线程上运行您的代码,因此ForEach之外的任何通信必须与可以处理并发更新的对象一起。 List 不能,但ConcurrentBag 可以。

#3


2  

ConcurrentBag is the correct answer, only in .NET 4.0 it is very slow. This has been fixed in .NET 4.5. See http://ayende.com/blog/156097/the-high-cost-of-concurrentbag-in-net-4-0

ConcurrentBag是正确答案,仅在.NET 4.0中它非常慢。这已在.NET 4.5中修复。见http://ayende.com/blog/156097/the-high-cost-of-concurrentbag-in-net-4-0

Both ConcurrentStack and ConcurrentQueue will also work in your situation...

ConcurrentStack和ConcurrentQueue也适用于您的情况......