为了账号安全,请及时绑定邮箱和手机立即绑定

Java - CountDownLatch.await() 可以由编译器重新排序吗

Java - CountDownLatch.await() 可以由编译器重新排序吗

缥缈止盈 2024-01-05 17:05:19
我必须在不同的系统上调用操作。另一个系统是高并发、分布式的。因此我通过 MessageBus 集成它。需要一种实现来让调用者等待,直到在总线上收到结果或超时到期。实现包括三个步骤:首先,我必须将 future 和 CountDownLatch(一旦收到结果就释放)打包到 ConcurrentHashMap 中。该映射与侦听 MessageBus 的组件共享。然后我必须开始执行并最后等待闩锁。public FailSafeFuture execute(Execution execution,long timeout,TimeUnit timeoutUnit) {    //Step 1    final WaitingFailSafeFuture future = new WaitingFailSafeFuture();    final CountDownLatch countDownLatch = new CountDownLatch(1);    final PendingExecution pendingExecution = new PendingExecution(future, countDownLatch);    final String id = execution.getId();    pendingExecutions.put(id, pendingExecution); //ConcurrentHashMap shared with Bus    //Step 2    execution.execute();    //Step 3    final boolean awaitSuccessfull = countDownLatch.await(timeout, timeoutUnit);    //...    return future;}所以问题是:编译器可以对这 3 个步骤重新排序吗?据我了解,只有步骤1和步骤3形成了发生之前的关系。因此理论上,第 2 步可以由编译器自由移动。是否可以将步骤 2 移到等待后面,从而使代码无效?后续问题:用共享对象上的等待/通知组合替换 CountDownLatch 是否可以解决问题而无需进一步同步(当然不考虑超时)
查看完整描述

1 回答

?
一只名叫tom的猫

TA贡献1906条经验 获得超2个赞

如果最终结果保持不变(就编译器的想法而言),则可能会发生指令重新排序,并且如果涉及多个线程,则可能需要额外的同步(因为编译器不知道其他线程可能期望特定的顺序)。

在单个线程中,如您的示例所示,所有步骤都相互关联happens-before。即使编译器可以重新排序这些方法调用,最终结果也需要相同(execute()之前调用await())。由于await()涉及同步,execute()除非您使用有错误的疯狂实现,否则不可能以某种方式在它之后滑动。

happens-before之间的关系确保代码在代码执行之前发生。所以显示的代码没有任何问题。countDown()await()PendingExecutionawait()

您应该始终更喜欢这些java.util.concurrentwait/notify,因为它们更易于使用并且提供更多功能。


查看完整回答
反对 回复 2024-01-05
  • 1 回答
  • 0 关注
  • 41 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信