.NET(C#):警惕PLINQ结果的无序性
PLINQ的运行结果是无序的,也就是不保持原来集合的顺序来操作(当然除了一些专门的排序操作)。原因则是线程的并发执行本来就充满了不确定性,把原来一个任务分割成好几个部分同时进行返回的结果会打乱原来的顺序,如果要强制保留顺序,肯定要浪费一些性能,PLINQ是可以这样的,但默认不这样。
先看一个LINQ示例:
var arr = new int[] { 1, 2, 3, 4, 5 };
var res = arr.Where(i => i != 3);
结果是:
1, 2, 4, 5
顺序是保持的。而PLINQ:
var res = arr.AsParallel().Where(i => i != 3);
结果顺序变了:
1, 4, 5, 2
使用PLINQ的AsOrdered和AsUnordered可以命令PLINQ执行保留原集合顺序或者不保留。
把上面的PLINQ改成:
var res = arr.AsParallel().AsOrdered().Where(i => i != 3);
结果就是:1, 2, 4, 5了。
不过如果对PLINQ集合进行了排序那么后续操作会自动保持顺序,就像调用了AsOrdered。
var res = arr.AsParallel().OrderBy(i => i).Where(i => i != 3);
结果也是:1, 2, 4, 5了。
注意某些PLINQ方法如果没有保持顺序执行意义不大,比如Reverse方法:
var res = arr.AsParallel().Reverse();
结果会是:
5, 3, 2, 1, 4