[英]Using atom and future is creating race condition in my Clojure program
我有一個用Clojure編寫的Web服務。 它實現了一個簡單的GET方法,該方法返回一個代表路由器當前位置和不同時間計數器的JSON對象。
我的代碼中有一堆原子來跟蹤時間。 每個原子代表機器在給定時間可能執行的不同活動。 例如:校准,空閑,卡住或工作:
(def idle-time (atom 0))
(def working-time (atom 0))
(def stuck-time (atom 0))
(def calibration-time (atom 0))
最后,我有一個循環,每15秒更新一次位置和時間計數器:
(defn update-machine-info []
(let [machine-info (parse-data-files)]
(update-time-counters machine-info)
(reset! new-state (merge machine-info
{:idleCounter @idle-time
:workingCounter @working-time
:stuckCounter @stuck-time
:calibrationCounter @calibration-time}))))
(loop []
(future
(Thread/sleep 15000)
(update-machine-info)
(recur)))
當前,此代碼進入競爭狀態,這意味着位置和時間計數器未更新。 但是,盡管具有舊值,Web Service仍會返回正確的JSON響應。
Web Service正在使用Cheshire將地圖生成為JSON,這是我的GET實現:
(defroutes app-routes
(GET "/" [] (resource :available-media-types ["application/json"]
:handle-ok (generate-string (get-machine-information))))
(route/not-found "Not Found"))
我應該使用引用而不是原子嗎? 我是否正確使用Future? 是(Thread / sleep 15000)導致此問題的,因為原子是異步的?
如果您在我的代碼中看到明顯的錯誤,請告訴我。
我不認為您可以可靠地在將來內部重現到將來之外的循環(不確定),但是為什么不嘗試這樣的事情呢?
(future
(loop []
(Thread/sleep 15000)
(update-machine-info)
(recur)))
這樣,循環/重復將保持在同一線程內。
除此之外,如果update-machine-counters引發異常,則循環可能會停止,並且您將永遠不會看到該異常,因為將來不會被取消引用。 代理( http://clojure.org/agents )可能更適合此操作,因為您可以注冊錯誤處理程序。
我認為正在發生的事情是,您調用期貨的過程在您的期貨實際執行之前就已經終止。 對於您的所作所為,期貨可能是錯誤的構造類型。 我也不認為您的循環將來記錄順序會按照您的想法進行。
這里尚有很多猜測,因為尚不清楚您實際在何處定義和調用代碼。 我認為您可能想使用類似代理的東西,您需要在根進程中進行設置,然后在返回響應之前在處理程序中向他們發送消息。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.