Clojure:阻止使用原子?

Clojure: block the use of an atom?

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

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

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

使用代理。

请参阅有关使用它们打印到控制台的 Using agents to serialise access to non-threadsafe resources 部分

除非您已经为您的示例大大简化了问题,否则看起来 swap!- 将当前计数器值设为零就足够了:

(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!