我有一个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}}已执行。我该怎么做?
答案 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部分,了解如何使用它们打印到控制台