gpt4 book ai didi

clojure - 了解 Clojure 中的 STM 属性

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

我正在阅读 7 周内的 7 个并发模型 这本书。在其中,哲学家被表示为多个 ref:

(def philosophers (into [] (repeatedly 5 #(ref :thinking))))

每个哲学家的状态在:thinking:eating 之间翻转,使用dosync 事务来确保一致性。

现在我想要一个输出当前状态的线程,这样我就可以确定状态在任何时候都是有效的:

(defn status-thread []
(Thread.
#(while true
(dosync
(println (map (fn [p] @p) philosophers))
(Thread/sleep 100)))))

我们使用多个@ 来读取每个哲学家的值。当我们 map 哲学家时,一些 refs 可能会发生变化。它会导致我们打印不一致的状态吗?

我知道 Clojure 使用 MVCC 来实现 STM,但我不确定我是否正确应用了它。

我的交易包含副作用,通常它们不应出现在交易中。但在这种情况下,交易总是会成功,副作用应该只发生一次。可以接受吗?

最佳答案

您的交易并不真的需要副作用,如果您将问题扩大到足够大,我相信交易可能会因为缺少历史记录而失败,如果有大量写入,则重试副作用继续。我认为这里更合适的方法是将 dosync 拉近。交易应该是一个纯粹的、无副作用的事实调查任务。一旦产生了一个值,您就可以在不影响 STM 的情况下自由地使用它执行副作用。

(defn status-thread []
(-> #(while true
(println (dosync (mapv deref philosophers)))
(Thread/sleep 100))
Thread.
.start)) ;;Threw in starting of the thread for my own testing

这里我想提几点:

  1. @deref fn 的阅读器宏,所以 (fn [p] @p) 等同于 取消引用
  2. 您应该避免事务中的惰性,因为某些惰性值可能会在dosync 的上下文之外进行评估,或者根本不会进行评估。对于 mapping,这意味着您可以使用例如doall,或者像这里一样只是热切评估的 mapv 变体,它生成一个向量而不是一个序列。

关于clojure - 了解 Clojure 中的 STM 属性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38569770/

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