CompletableFuture、可变对象和内存可见性

CompletableFuture, mutable objects and memory visibility

我正在尝试了解 Java 8 中的 CompletableFuture 如何与 Java memory model 交互。在我看来,为了程序员的理智,理想情况下应满足以下条件:

  1. 线程中完成 CompletableFuture happen-before 任何 completions 相关阶段的操作被执行
  2. 注册完成 线程中的操作创建依赖阶段发生在 完成 执行依赖阶段

java.util.concurrent documentation 中有一条注释说:

Actions in a thread prior to the submission of a Runnable to an Executor happen-before its execution begins. Similarly for Callables submitted to an ExecutorService.

这表明第一个属性是正确的,只要完成未来的线程执行完成依赖阶段或将其提交给Executor。另一方面,在阅读 CompletableFuture documentation 之后,我对此不太确定:

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.

这让我想到了我的问题:

  1. 以上两个假设属性是否属实?
  2. 在使用 CompletableFuture 时是否有任何关于存在或缺乏内存可见性保证的特定文档?

附录:

以具体示例的方式,考虑这段代码:

List<String> list1 = new ArrayList<>();
list1.add("foo");

CompletableFuture<List<String>> future =
        CompletableFuture.supplyAsync(() -> {
            List<String> list2 = new ArrayList<>();
            list2.addAll(list1);
            return list2;
        });

"foo"list1能保证lambda函数可见吗? list2添加list1是否保证对future的依赖阶段可见?

  1. 是的,你的两个假设都是正确的。原因是,CompletableFuture 中的所有 *Async() 方法都将使用 java.util.concurrent.Executor 进行异步调用。如果您不提供,这将是每个任务的 common pool or an Executor that creates a new thread(如果您将公共池的大小限制为 0 或 1)或用户提供的执行器。 正如您已经发现的,Executordocumentation 表示:

    Actions in a thread prior to submitting a Runnable object to an Executor happen-before its execution begins, perhaps in another thread.

    因此,在您的示例中,可以保证 "foo" 是您的 lambda 中 list1 的一部分,并且 list2 在后续阶段可见。

  2. Executor.

  3. 的文档基本涵盖了这个