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

时间:2015-12-23 03:03:20

标签: java java-8 java.util.concurrent java-memory-model completable-future

我试图了解Java 8中的CompletableFuture如何与Java memory model进行交互。在我看来,对于程序员的理智,理想情况下应该成立:

  1. 完成CompletableFuture 的线程中的操作在任何完成依赖阶段执行之前发生
  2. 注册完成的线程中的操作创建一个依赖阶段发生 - 执行完成依赖阶段
  3. java.util.concurrent documentation中有一条说明:

      

    Runnable 提交Executor之前,线程中的操作发生在执行开始之前。同样,Callable提交给ExecutorService

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

      

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

    这让我想到了我的问题:

    1. 这两个假设属性是否真实?
    2. 使用CompletableFuture时,是否存在关于是否存在内存可见性保证的特定文档?
    3. 附录:

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

      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函数可见?是否可以保证list1的相关阶段可以看到list2 future {/ 1}}?

1 个答案:

答案 0 :(得分:3)

  1. 是的,你的两个假设都是正确的。原因是,*Async()中的所有CompletableFuture方法都将使用java.util.concurrent.Executor进行异步调用。如果您没有提供,那么这将是common pool或为每个任务创建new thread的执行者(如果您将公共池的大小限制为0或1)或者用户提供的执行程序。 正如您已经发现的那样,Executor的{​​{3}}说:

      

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

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

  2. 这基本上由Executor

  3. 的文档涵盖