65.9K
CodeProject 正在变化。 阅读更多。
Home

PLinq 和源 IEnumerable 的线程安全

emptyStarIconemptyStarIconemptyStarIconemptyStarIconemptyStarIcon

0/5 (0投票)

2012 年 9 月 3 日

Apache
viewsIcon

8265

PLinq 和源 IEnumerable 的线程安全

当我发现 PLINQ 从多个线程调用源 IEnumerable 时,我开始思考:这怎么可能工作?例如,当有人编写如下代码时

Enumerable.Range(1,1000).AsParallel()...

Range 迭代器必须在某个变量中保存其当前状态。如果这个状态从多个线程访问,如何避免竞态条件?以下是我的发现:

1. Enumerable.Range() 返回一个 IEnumerable<int>。这个可枚举对象的 GetEnumerator() 将为不同的线程返回不同的枚举器。这似乎是使用 yield return 关键字生成的枚举器的内置特性。Reflector 是我的见证。证明链接

然而,每个枚举器 并非 线程安全的,并且没有任何锁定代码。

2. AsParallel() 只调用一次 GetEnumerator(),然后从多个线程使用它,因此上述保护措施不起作用。

3. 微软的 Stephen Toub 表示,由于 IEnumerable 本身就不是线程安全的,PLINQ 已经内置了锁定机制。

4. 根据 Reflector,这似乎是在 PartitionedDataSoruce<T>.MoveNext() 方法中实现的。

所以,放轻松吧。你的枚举器可以并且将会是线程不安全的,PLINQ 已经有了自己的锁来处理这个问题。

© . All rights reserved.