I'm trying to understand how CompletableFuture
in Java 8 interacts with the Java memory model. It seems to me that for programmer sanity, the following should ideally hold true:
- Actions in the thread that completes a
CompletableFuture
happen-before anycompletionsdependent stages are executed - Actions in the thread that
registers a completioncreates a dependent stage happen-before thecompletiondependent stage is executed
There's a note in java.util.concurrent documentation saying that:
Actions in a thread prior to the submission of a
Runnable
to anExecutor
happen-before its execution begins. Similarly forCallable
s submitted to anExecutorService
.
Which would suggest that the first property is true, as long as the thread that completes the future executes the completion dependent stage or submits it to an Executor
. On the other hand, after reading CompletableFuture documentation I'm not so sure about that:
Actions supplied for dependent completions of non-async methods may be performed by the thread that completes the current
CompletableFuture
, or by any other caller of a completion method.
Which brings me to my questions:
- Are the two hypothetical properties above true or not?
- Is there any specific documentation anywhere about the presence or lack of memory visibility guarantees when working with
CompletableFuture
?
Addendum:
In the way of a concrete example, consider this code:
List<String> list1 = new ArrayList<>();
list1.add("foo");
CompletableFuture<List<String>> future =
CompletableFuture.supplyAsync(() -> {
List<String> list2 = new ArrayList<>();
list2.addAll(list1);
return list2;
});
Is it guaranteed that adding "foo"
to list1
is visible to the lambda function? Is it guaranteed that adding list1
to list2
is visible to the dependent stages of future
?