Clojure:阻止使用原子?

时间:2017-03-06 07:14:11

标签: multithreading clojure atomic

我有一个Clojure代码,它并行运行几个线程。它们共享一个原子:(def counter (atom 0)),每个线程递增一次。每隔10分钟,我想使用原子的值执行几个动作,然后将其重置为0 - 例如:

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

重要的是counter的值从取消引用的那一刻到重置的那一刻都不会改变 - 这意味着当试图改变原子的值时,所有线程都应该被阻塞{ {1}}已执行。我该怎么做?

2 个答案:

答案 0 :(得分:3)

除非你已经大大简化了你的例子的问题,看起来像swap! - 在这里用0表示当前的计数器值就足够了:

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

所以你只需将旧的计数器值保存在局部变量中,用零自动交换它,然后执行任何需要处理旧值的记录 - 所有这些都不会拖延任何其他线程所需的时间超过{{ 1}}

答案 1 :(得分:2)

使用代理。

请参阅Using agents to serialise access to non-threadsafe resources部分,了解如何使用它们打印到控制台