簡體   English   中英

在我的Clojure程序中使用原子和未來正在創造競爭條件

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM