简体   繁体   English

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

[英]CompletableFuture, mutable objects and memory visibility

I'm trying to understand how CompletableFuture in Java 8 interacts with the Java memory model . 我试图了解Java 8中的CompletableFuture如何与Java内存模型交互。 It seems to me that for programmer sanity, the following should ideally hold true: 在我看来,对于程序员的理智,理想情况下应该成立:

  1. Actions in the thread that completes a CompletableFuture happen-before any completions dependent stages are executed 完成CompletableFuture的线程中的操作发生在执行任何 完成 相关的阶段之前
  2. Actions in the thread that registers a completion creates a dependent stage happen-before the completion dependent stage is executed 注册完成 的线程中的操作会在执行 完成 依赖阶段之前创建依赖阶段

There's a note in java.util.concurrent documentation saying that: java.util.concurrent文档中有一条说明:

Actions in a thread prior to the submission of a Runnable to an Executor happen-before its execution begins. 在提交之前,操作在一个线程RunnableExecutor 发生-before其执行开始。 Similarly for Callable s submitted to an ExecutorService . 类似地, Callable被提交给ExecutorService

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 . 这表明第一个属性为true,只要完成将来的线程执行 完成 依赖阶段或将其提交给Executor On the other hand, after reading CompletableFuture documentation I'm not so sure about that: 另一方面,在阅读CompletableFuture文档后,我不太确定:

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. 为非异步方法的依赖完成提供的动作可以由完成当前CompletableFuture的线程执行,或者由完成方法的任何其他调用者执行。

Which brings me to my questions: 这让我想到了我的问题:

  1. Are the two hypothetical properties above true or not? 这两个假设属性是否真实?
  2. Is there any specific documentation anywhere about the presence or lack of memory visibility guarantees when working with CompletableFuture ? 在使用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? 是否保证将list1函数可以看到向list1添加"foo" Is it guaranteed that adding list1 to list2 is visible to the dependent stages of future ? 是否可以保证将list1添加到list2future的依赖阶段是否可见?

  1. Yes, both of your hypotheses are true. 是的,你的两个假设都是正确的。 The reason is, that all of the *Async() methods in CompletableFuture will use a java.util.concurrent.Executor to make the asynchronous call. 原因是, CompletableFuture中的所有*Async()方法都将使用java.util.concurrent.Executor进行异步调用。 If you don't provide one, this will either be the common pool or an Executor that creates a new thread for each task (in case you restrict the size of the common pool to 0 or 1) or a user-provided Executor. 如果您不提供,则可以是公共池 ,也可以是为每个任务创建新线程的Executor(如果您将公共池的大小限制为0或1)或用户提供的Executor。 As you already found out, the documentation of the Executor says: 正如您已经发现的那样, Executor文档说:

    Actions in a thread prior to submitting a Runnable object to an Executor happen-before its execution begins, perhaps in another thread. 在将Runnable对象提交给Executor之前,线程中的操作发生在执行开始之前,可能在另一个线程中。

    So in your example, it is guaranteed that "foo" is part of list1 in your lambda and that list2 is visible in subsequent stages. 因此,在您的示例中,保证"foo"是lambda中list1一部分,并且list2在后续阶段中可见。

  2. This is basically covered by the documentation of Executor . 这基本上由Executor的文档涵盖。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM