gpt4 book ai didi

transactions - 在 Clojure 中同步读写的方法?

转载 作者:行者123 更新时间:2023-12-04 14:17:00 25 4
gpt4 key购买 nike

在网络应用程序中,我试图从有限的 id 池中生成一个唯一的线程安全 id。我面临的问题是在读写之间另一个线程可能已经改变了数据结构;这就是为什么我必须求助于 compare-and-set! .

(def sid-batch 10)
(def sid-pool (atom {:cnt 0
:sids '()}))

(defn get-sid []
(let [{:keys [cnt sids] :as old} @sid-pool]

; use compare-and-set! here for atomic read & write
(if (empty? sids)

; generate more sids
(if (compare-and-set!
sid-pool
old
(-> old
(assoc :sids (range (inc cnt) (+ sid-batch cnt)))
(assoc :cnt (+ cnt sid-batch))))

; return newest sid or recur till "transaction" succeeds
cnt
(recur))

; get first sid
(if (compare-and-set! sid-pool old (update-in old [:sids] next))

; return first free sid or recur till "transaction" succeeds
(first sids)
(recur)))))

是否有一种更简单的方法来同步读取和写入,而不必“手动”执行 STM 并且不滥用 sid-pool 中的字段作为来自 swap! 的返回值?

最佳答案

您可以通过向 sid-pool 添加一个字段来使用原子来完成此操作。以您似乎建议的方式。我同意这有点恶心,但使用 compare-and-swap!因为这么简单的事情太可怕了。相反,使用原子;或者一个 ref,它可以让你从 dosync 返回任何你想要的东西在交易安全的同时阻止:

(defn get-sid []
(dosync
(let [{:keys [cnt sids]} @sid-pool]
(if (empty? sids)
(do
(alter sid-pool
(fn [old]
(-> pool
(assoc :sids (range (inc cnt) (+ sid-batch cnt)))
(update-in [:cnt] + sid-batch))))
cnt)
(do
(alter sid-pool update-in [:sids] next)
(first sids))))))

关于transactions - 在 Clojure 中同步读写的方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9940397/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com