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

A.L*_*.L. 20 java java.util.concurrent java-memory-model java-8 completable-future

我试图理解CompletableFutureJava 8 如何与Java内存模型交互.在我看来,对于程序员的理智,理想情况下应该成立:

  1. 完成任务的线程中的操作CompletableFuture - 在执行任何完成相关的阶段之前
  2. 在该线程操作注册完成创建依赖阶段发生,之前完成执行依赖阶段

java.util.concurrent文档中有一条说明:

在提交Runnable到执行之前的线程中的操作Executor - 在执行开始之前.同样的Callables提交给ExecutorService.

这表明第一个属性为true,只要完成未来的线程执行完成依赖阶段或将其提交给Executor.另一方面,在阅读CompletableFuture文档后,我不太确定:

为非异步方法的依赖完成提供的动作可以由完成当前的线程执行CompletableFuture,或者由完成方法的任何其他调用者执行.

这让我想到了我的问题:

  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;
        });
Run Code Online (Sandbox Code Playgroud)

能够保证所有的加入"foo"list1是可见的lambda函数?是否保证添加list1list2依赖阶段是可见的future

Ste*_*stl 5

  1. 是的,你的两个假设都是正确的。原因是,中的所有*Async()方法都CompletableFuture将使用 ajava.util.concurrent.Executor进行异步调用。如果您不提供,这将是公共池或为每个任务创建新线程的 Executor (如果您将公共池的大小限制为 0 或 1)或用户提供的 Executor。正如您已经发现的那样,文档Executor说:

    在将 Runnable 对象提交给 Executor 之前,线程中的操作发生在其执行开始之前,可能在另一个线程中。

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

  2. 这基本上由Executor.