我有一个原子包裹物品的矢量:
(def items (atom [1 2 3 4]))
Run Code Online (Sandbox Code Playgroud)
我想原子地删除第一个项目并将其返回.此代码说明了逻辑:
(let [x (first @items)]
(swap! items #(subvec % 1))
x)
Run Code Online (Sandbox Code Playgroud)
但是当许多线程相互竞争时,上面的代码是不正确的.阅读和更新之间存在竞争条件.
正如在这个答案中所说的那样,原子用于不协调的同步访问.我希望这可以用原子而不是ref来完成,因为原子更简单.
有没有只使用原子的解决方案,而不是refs?(我将尝试使用手表,看看情况如何.)如果你的答案坚持需要参考,你能否解释一下为什么需要参考,即使建议在需要"协调同步访问许多身份时参考" "(与上述相同的链接).
这与其他相关问题不同,例如如何在Clojure中更新原子的向量元素?和在Clojure中删除原子列表中项目的最佳方法,因为我想更新一个向量原子并返回该值.
A. *_*ebb 11
旋转环compareAndSet用于swap!原子.Clojure还compare-and-set!为原子提供了较低级别,您可以使用它来执行自己的自旋循环并返回旧值和新值.
(defn swap*!
"Like swap! but returns a vector of [old-value new-value]"
[atom f & args]
(loop []
(let [ov @atom
nv (apply f ov args)]
(if (compare-and-set! atom ov nv)
[ov nv]
(recur)))))
(defn remove-first-and-return [atom]
(let [[ov nv] (swap*! atom subvec 1)]
(first ov)))
Run Code Online (Sandbox Code Playgroud)