CompletableFuture、可变对象和内存可见性
CompletableFuture, mutable objects and memory visibility
我正在尝试了解 Java 8 中的 CompletableFuture
如何与 Java memory model 交互。在我看来,为了程序员的理智,理想情况下应满足以下条件:
- 线程中完成
CompletableFuture
happen-before 任何 completions 相关阶段的操作被执行
注册完成 线程中的操作创建依赖阶段发生在 完成 执行依赖阶段
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 Callable
s 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.
这让我想到了我的问题:
- 以上两个假设属性是否属实?
- 在使用
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
的依赖阶段可见?
是的,你的两个假设都是正确的。原因是,CompletableFuture
中的所有 *Async()
方法都将使用 java.util.concurrent.Executor
进行异步调用。如果您不提供,这将是每个任务的 common pool or an Executor that creates a new thread(如果您将公共池的大小限制为 0 或 1)或用户提供的执行器。
正如您已经发现的,Executor
的 documentation 表示:
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
在后续阶段可见。
Executor
.
的文档基本涵盖了这个
我正在尝试了解 Java 8 中的 CompletableFuture
如何与 Java memory model 交互。在我看来,为了程序员的理智,理想情况下应满足以下条件:
- 线程中完成
CompletableFuture
happen-before 任何completions相关阶段的操作被执行 注册完成线程中的操作创建依赖阶段发生在完成执行依赖阶段
java.util.concurrent documentation 中有一条注释说:
Actions in a thread prior to the submission of a
Runnable
to anExecutor
happen-before its execution begins. Similarly forCallable
s submitted to anExecutorService
.
这表明第一个属性是正确的,只要完成未来的线程执行完成依赖阶段或将其提交给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.
这让我想到了我的问题:
- 以上两个假设属性是否属实?
- 在使用
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
的依赖阶段可见?
是的,你的两个假设都是正确的。原因是,
CompletableFuture
中的所有*Async()
方法都将使用java.util.concurrent.Executor
进行异步调用。如果您不提供,这将是每个任务的 common pool or an Executor that creates a new thread(如果您将公共池的大小限制为 0 或 1)或用户提供的执行器。 正如您已经发现的,Executor
的 documentation 表示: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
在后续阶段可见。Executor
. 的文档基本涵盖了这个