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 之前,不能保证这些更改对任何其他线程可见关系。因此,您可能需要额外的同步来对该对象实施线程安全。
我有一个调用分离线程的线程。它将相同的 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 之前,不能保证这些更改对任何其他线程可见关系。因此,您可能需要额外的同步来对该对象实施线程安全。