Given the following code:
final int n = 50;
final int[] addOne = new int[n];
IntStream.range(0, n)
.parallel()
.forEach(i -> addOne[i] = i + 1);
// (*) Are the addOne[i] values all visible here?
for (int value : addOne) {
System.out.println(value);
}
The question: After the worker threads have exited (i.e. at point (*)
), can it be guaranteed that the main thread will see all array contents written by the worker threads?
I am interested in understanding what the Java memory model says about the above question. This has nothing to do with the concurrency issues per se (i.e. the fact that parallel streams in Java can process their elements in any order). To preempt some replies, I know that it is impossible to guarantee memory ordering semantics between two different threads with access to the same array element in Java without using something like AtomicReferenceArray<E>
. For the purpose of this question, assume that Atomic*
classes will not be used by parallel workers. More importantly, note that no two worker threads ever try to write to the same array element, since all the i
values are unique. Therefore memory ordering semantics between threads are not important here, only whether any value written to an array element by a worker thread will always be visible to the main thread after the parallel stream has ended.
There is a computational "barrier" between initializing the array elements in the main thread and launching the parallel worker threads (the workers will always initially see elements with their zero initializer value). And there is a completion barrier that waits for all workers to complete at the end of the stream before handing control back to the main thread. So really the question reduces to whether a total ordering or implicit "memory flush barrier" can be assumed when a computational barrier is imposed at the end of a parallel stream.
Asked another way, is there any chance at all that the main thread might read the default initialization value of 0
for some element after point (*)
? Or will the CPU cache hierarchy always ensure that the main thread will see the most recent value written to the array by a worker thread, even if that value hasn't been flushed out of the CPU cache back to RAM yet?
I am assuming for the purposes of this question that it takes zero time to return control to the main thread after the parallel stream has completed, so there is no race condition that happens to cause the array values to be flushed to RAM due to the time it takes to shut down the parallel stream, or due to the amount of cache eviction that has to take place to shut down the parallel stream.