2017-03-06 75 views
0

我有一個並行運行幾個線程的Clojure代碼。它們都共享一個原子:(def counter (atom 0)),它由每個線程遞增。每10分鐘後,我想執行使用原子值幾個動作,然後重置回0 - 例如:Clojure:阻止使用原子?

(defn publish-val [] 
    (let [c @counter] 
    (email c) 
    (statsd c) 
    (print-log c) 
    (reset! counter 0))) 

說的counter值將不會從此刻改變是很重要的它被解除引用到它被重置的那一刻 - 這意味着在嘗試更改原子值時所有線程都應該被阻塞,而執行publish-val。我該怎麼做呢?

回答

3

除非你已經大大簡化了你的榜樣的問題,它看起來像swap! -ing出與零電流計數器的值就足夠了這裏:

(defn publish-val [] 
    (with-local-vars [c nil] 
    (swap! counter 
      (fn [x] (var-set c x) 0)) 
     (email @c) 
     (statsd @c) 
     (print-log @c))) 

所以,你只需保存你的舊計數器值在一個局部變量,零原子交換,然後做舊做任何簿記需要的價值都沒有拖延任何其他線程長的比它採取到swap!

+0

我覺得'(with-local-vars [c nil](重置!計數器(do(var-set c @counter)0))(println @c))'在這裏更準確..你有什麼理由喜歡'swap!'和'fn [c]'? – shakedzy

+1

@shakedzy - 使用'swap!'保證原子性。如果您使用'reset!',您可能會在讀'@ counter'和調用'(reset!counter 0)''之間丟失'counter'的一些更新。 – DaoWen