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]);
Is this code guaranteed to output "106"?
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).
But Collection.parallelStream()
is not documented to establish such a relationship...
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]);
}
Or... does parallelStream()
actually provide these happens-before relationships, and this simply a matter of some missing documentation?
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.