Collection.parallelStream()是否暗示先发生关系? [英] Does Collection.parallelStream() imply a happens-before relationship?
问题描述
考虑以下(完全人为设计的)Java代码:
Consider this (completely contrived) Java code:
final List<Integer> s = Arrays.asList(1, 2, 3);
final int[] a = new int[1];
a[0] = 100;
s.parallelStream().forEach(i -> {
synchronized (a) {
a[0] += i;
}
});
System.out.println(a[0]);
此代码是否保证输出"106"?
Is this code guaranteed to output "106"?
除非是由parallelStream()
建立的 happens-before 关系,否则似乎不是这样,通过该关系我们可以肯定地知道对lambda中的a[0]
的首次访问将看到100
而不是零(根据我对Java内存模型的理解).
It seems like it is not unless there is a happens-before relationship established by parallelStream()
, by which we can know for sure that the first accesses to a[0]
in the lambda will see 100
and not zero (according to my understanding of the Java memory model).
但是Collection.parallelStream()
并没有证明可以建立这种关系...
But Collection.parallelStream()
is not documented to establish such a relationship...
可以问相同的问题来完成parallelStream()
方法调用.
The same question can be asked for the completion of the parallelStream()
method invocation.
那么我是不是缺少了什么?或者为正确起见,是否需要上面的代码看起来像这样呢?
So am I missing something, or is it true that for correctness would the above code be required to look something like this instead:
final List<Integer> s = Arrays.asList(1, 2, 3);
final int[] a = new int[1];
synchronized (a) {
a[0] = 100;
}
s.parallelStream().forEach(i -> {
synchronized (a) {
a[0] += i;
}
});
synchronized (a) {
System.out.println(a[0]);
}
或者... parallelStream()
确实提供了这些先发生关系,而这仅仅是一些缺少文档的问题吗?
Or... does parallelStream()
actually provide these happens-before relationships, and this simply a matter of some missing documentation?
我之所以问是因为,从API设计的角度来看,(至少对我来说)这样做似乎是合乎逻辑的……类似于Thread.start()
等.
I'm asking because from an API design perspective, it seems (to me at least) like this would be a logical thing to do... analogous to Thread.start()
, etc.
推荐答案
您真的应该避免在管道外部"访问变量.即使您使其正常工作,性能也可能会受到影响. JDK内置了许多工具来实现此目的.例如,您的用例可能更安全,例如:
You really should avoid hitting variables 'outside' the pipeline. Even if you get it to work correctly performance will likely suffer. There are a lot of tools to achieve this built into the JDK. For example your use case is probably safer with something like:
Integer reduce = IntStream.of(1, 2, 3)
.parallel()
.reduce(100, (accumulator, element) -> accumulator + element);
这篇关于Collection.parallelStream()是否暗示先发生关系?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!