可兼容未来、可变对象和内存可见性

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

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

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

线程中的操作在提交到 happen 之前 (在其执行开始之前)。同样,对于 提交给 .RunnableExecutorCallableExecutorService

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

为非异步方法的依赖完成提供的操作可以由完成当前方法的线程执行,也可以由完成方法的任何其他调用方执行。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;
        });

是否保证添加到对 lambda 函数可见?是否可以保证 添加到 对 的依赖阶段可见?"foo"list1list1list2future


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

    在将 Runnable 对象提交给执行程序之前,线程中的操作发生在执行器的执行开始之前,也许在另一个线程中。

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

  2. 这基本上包含在 的文档中。Executor


答案 2

推荐