static void statefullParallelLambdaSet() {
Set<Integer> s = new HashSet<>(
Arrays.asList(1, 2, 3, 4, 5, 6)
);
List<Integer> list = new ArrayList<>();
int sum = s.parallelStream().mapToInt(e -> { // pipeline start
if (list.size() <= 3) { // list.size() changes while the pipeline operation is executing.
list.add(e); // mapToInt's lambda expression depends on this value, so it's stateful.
return e;
}
else return 0;
}).sum(); // terminal operation
System.out.println(sum);
}
在上面的代码中,它说list.size()在管道操作运行时发生变化,但我不明白。
因为list.add(e)是并行执行的,所以它会在多个线程中同时执行,那么假设每次执行时值都会改变是否正确呢?
值即使作为串行流执行也会改变的原因是因为它是一个集合,所以没有顺序,所以每次执行时绘制的数字都不一样...
我说的对吗?
1条答案
按热度按时间9jyewag01#
发生这种情况的原因是所谓的争用条件,CPU(即使是许多线程化CPU)运行的进程也比应用程序进程多,因此它可以解析并执行指令评估,然后必须跳出来为操作系统做一些事情,然后返回,应用程序的另一个并行进程设法通过它,因为核心/超线程没有从其工作中被窃取。
你可以在以下书籍中读到有关竞争条件的内容:https://link.springer.com/referenceworkentry/10.1007/978-0-387-09766-4_36
但是你应该做的是在你要修改的内存上实现锁来防止这种情况,在Java中你需要查看
java.util.concurrent.Locks
https://www.baeldung.com/java-concurrent-locks