CompletableFutures 线程安全吗?

Are CompletableFutures thread safe?

我有一个调用分离线程的线程。它将相同的 CompletableFuture 传递给这两个子线程。如果 .get() 在这两个线程中同时被调用,我会遇到任何类型的并发问题吗?

public void mainClass(CompletableFuture<ObjA> cfInput){
  class1.doAsync1(cfInput);
  class2.doAsync2(cfInput);
}

@Async
public void doAsync1(CompletableFuture<ObjA> cfInput){
  //logic
  System.out.println(cfInput.get().getObjA().getBlah());
  //logic
}

@Async
public void doAsync2(CompletableFuture<ObjA> cfInput){
  //logic
  System.out.println(cfInput.get().getObjA.getBlah());
  //logic
}

public class ObjA(){
  private ObjB objB;
  public ObjB getObjB();
  public void setObjB();
}
public class ObjA(){
  private String blah;
  public String getBlah();
  public void setBlah();
}

CompletableFuture 本质上是线程安全的

您可以根据 class 设计用于多线程上下文这一事实来简单地假设这一点,但是在 the description of the java.util.concurrent package:

中更明确地指定了这一点

Memory Consistency Properties

Chapter 17 of the Java Language Specification defines the happens-before relation on memory operations such as reads and writes of shared variables. The results of a write by one thread are guaranteed to be visible to a read by another thread only if the write operation happens-before the read operation. […] The methods of all classes in java.util.concurrent and its subpackages extend these guarantees to higher-level synchronization. In particular:

  • […]
  • Actions taken by the asynchronous computation represented by a Future happen-before actions subsequent to the retrieval of the result via Future.get() in another thread.

因此,这意味着线程在完成未来之前执行的任何写入对于在该未来调用 get() 的任何其他线程都是可见的(即它“happened-之前”)。

您的对象不是本质上线程安全的

……它们也不受CompletableFuture

“保护”

尽管 CompletableFuture 本身是线程安全的,并且为您的写入的可见性提供了一些保证,但它不会使您的对象线程安全。

例如,如果您修改了 CompletableFuture.get() 返回的对象,则在您输入另一个 happens-before 之前,不能保证这些更改对任何其他线程可见关系。因此,您可能需要额外的同步来对该对象实施线程安全。