与Parallel.ForEach产量返回线程安全() [英] Thread safety of yield return with Parallel.ForEach()
问题描述
考虑下面的代码示例,它创建一个整数枚举集合并同时对其进行处理:
Consider the following code sample, which creates an enumerable collection of integers and processes it in parallel:
using System.Collections.Generic;
using System.Threading.Tasks;
public class Program
{
public static void Main()
{
Parallel.ForEach(CreateItems(100), item => ProcessItem(item));
}
private static IEnumerable<int> CreateItems(int count)
{
for (int i = 0; i < count; i++)
{
yield return i;
}
}
private static void ProcessItem(int item)
{
// Do something
}
}
能够保证所有的由 Parallel.ForEach()生成的工作线程code>每得到一个不同的项目或者是周围的增量部分锁定机制和
我
要求?
Is it guaranteed that the worker threads generated by Parallel.ForEach()
each get a different item or is some locking mechanism around incrementation and returning of i
required?
推荐答案
Parallel.ForEach< TSource>
,当 TSource
是的IEnumerable< T>
,会为的IEnumerable℃的分区; T>
,它包含自己的的内部锁定机制,这样你就不会需要实现你的迭代任何线程安全。
Parallel.ForEach<TSource>
, when TSource
is an IEnumerable<T>
, creates a partitioner for the IEnumerable<T>
that includes its own internal locking mechanism, so you don't need to implement any thread-safety in your iterator.
每当一个辅助线程请求项目的块,分区程序将创建一个内部枚举的,其中:
Whenever a worker thread requests a chunk of items, the partitioner will create an internal enumerator, which:
- 获取共享锁
- 通过源迭代(从那里留下的)来获取项目的块,节省了在私人数组项
- 解除锁定,以便其他块请求可以被满足。
- 供应来自其私人阵列的工作线程。
- acquires a shared lock
- iterates through the source (from where it was left of) to retrieve the chunk of items, saving the items in an private array
- releases the lock so that other chunk requests can be fulfilled.
- serves the worker thread from its private array.
正如你所见,在运行通过在的IEnumerable< T>
进行分区的目的是顺序(通过共享锁访问),以及分区并行处理
As you see, the run through the IEnumerable<T>
for the purposes of partitioning is sequential (accessed via a shared lock), and the partitions are processed in parallel.
这篇关于与Parallel.ForEach产量返回线程安全()的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!