我必須在不同的系統上調用操作。另一個系統是高并發、分布式的。因此我通過 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條經驗 獲得超3個贊
如果最終結果保持不變(就編譯器的想法而言),則可能會發生指令重新排序,并且如果涉及多個線程,則可能需要額外的同步(因為編譯器不知道其他線程可能期望特定的順序)。
在單個線程中,如您的示例所示,所有步驟都相互關聯happens-before
。即使編譯器可以重新排序這些方法調用,最終結果也需要相同(execute()
之前調用await()
)。由于await()
涉及同步,execute()
除非您使用有錯誤的瘋狂實現,否則不可能以某種方式在它之后滑動。
和happens-before
之間的關系確保代碼在代碼執行之前發生。所以顯示的代碼沒有任何問題。countDown()
await()
PendingExecution
await()
您應該始終更喜歡這些java.util.concurrent
類wait/notify
,因為它們更易于使用并且提供更多功能。
添加回答
舉報
0/150
提交
取消