CompletableFuture是否线程安全?多线程同时调用get方法会有并发问题吗
多个线程同时调用同一个CompletableFuture实例的get()方法,本身不会产生和CompletableFuture相关的并发问题,针对你的三个疑问具体解答如下:
- 是否会损坏CompletableFuture实例?
不会。JDK中CompletableFuture的实现本身是线程安全的,它的状态流转、结果存储都通过CAS、volatile等机制保障并发场景下的正确性,多线程同时调用get()不会破坏实例内部结构,也不会触发逻辑异常。 - 是否有可能无法获取到.get()返回对象的最新变更?
不会。CompletableFuture用于存储结果的变量是volatile修饰的,根据Java内存模型的happen-before规则,CompletableFuture将结果写入volatile变量的操作,优先于所有后续线程读取该变量获取结果的操作。因此只要CompletableFuture已经完成,所有线程调用get()拿到的结果都是最终完成时的最新值,不存在可见性问题。 - 如果后续修改.get()返回的对象会有什么问题?
这部分风险和CompletableFuture本身无关。get()返回的是结果对象的引用,多个线程拿到的是同一个对象的引用,如果该对象不是线程安全的,且多线程同时修改它没有加同步措施,就会出现普通的线程安全问题:比如原子性问题导致的数据修改丢失、可见性问题导致其他线程看不到修改、指令重排导致的逻辑异常等。
示例代码疑问解答
你给出的场景中明确假设cfInput完成后没有任何操作修改它返回的对象,那么两个线程打印的结果一定是相同的,不会出现不同值的情况。原因是:
- 两个线程拿到的
ObjA是同一个实例引用,ObjB和内部的blah属性也没有被修改,读取的值自然一致; CompletableFuture的结果可见性保障,两个线程拿到的ObjA一定是完成后的最终状态,不会出现半初始化或者旧值的情况。
内容的提问来源于stack exchange,提问作者Brian
相关产品推荐
相关产品推荐

