【问题标题】:Single atom vs multiple refs单个原子与多个参考
【发布时间】:2013-11-19 05:45:57
【问题描述】:

使用单个 atom 和 hashmap 与多个 ref 表示状态的权衡是什么?

例如:

(def start (atom {:location "Chicago" :employer "John"}))

(def location (ref "Chicago"))
(def employer (ref "John"))

非常感谢

【问题讨论】:

    标签: concurrency clojure stm


    【解决方案1】:

    单原子版本更好,权衡更少。鉴于您不想更改雇主和不协调的位置,您的胜利是您不必创建dosync 块来更改位置或雇主或两者。使用原子,您可以简单地(swap! start assoc :location "baz")

    使用多个 refs 的一个重大权衡是,所有与 refs 的交易都将并行尝试,第一个准备好的交易将获胜,其他交易将重新启动。虽然对于 atom 也是如此,但为所有条目拥有更多的 ref 需要在幕后进行更多的监控、分组(对于 dosync 块)等。为了减少重新启动,将信息分组到哈希图中是有意义的。根据是否需要协调更改,将其放在 ref 或 atom 中。

    【讨论】:

      【解决方案2】:

      多个 Ref 允许更多的并发性,因为所有对 Atom 的写入都是线性化的。当没有冲突的写入时,STM 允许提交许多并行事务/ensures(此外,它还提供了commute,它允许进行某些通常会导致冲突的写入不这样做)。

      此外,STM 与代理合作——当且仅当事务提交时,才会执行从事务中发送到代理的操作。这允许人们从交易内部安全地产生副作用。 Atoms 没有提供类似的功能。

      权衡是 STM 的开销大于 Atom 的开销,而且有可能发生某些异常(写入偏差,请参阅 the Wikipedia page on snapshot isolation)。此外,在获取整个系统的快照时遇到严重问题时,可以使用 STM 实现出色的并发性;在这方面,请参阅 Christophe Grand 出色的 blog post 和他的 megaref 库。

      在许多情况下,人们发现只需将所有状态存储在单个 Atom 中就足够了,这绝对是一种更简单、更轻量级的方法。

      【讨论】:

      • +1 表示平衡的答案,但这让我有点困惑; Additionally, the STM cooperates with Agents -- actions sent to Agents from within a transaction will be performed if and only if the transaction commits. - 交换原子时不会执行操作吗?这看起来像是无论成功与否都会执行的操作。
      • 如果您在传递给swap! 的函数中send,那么是的,send 将在每次重试时重新执行。尝试例如(def a (atom 0)) (def ag (agent nil)) (do (future (swap! a (fn [x] (Thread/sleep 5000) (send ag println :foo) (inc x)))) (Thread/sleep 1000) (swap! a inc)):这里:foo会被打印两次;如果你使用 Ref 而不是 Atom,它只会被打印一次。
      【解决方案3】:

      我认为您不应该考虑在 atomsrefs 之间进行权衡,因为它们用于不同的情况。

      当您想要原子地更改单个事物时,您应该使用atom

      refs 使用 STM 并涉及在事务中同时更改许多不同的内容。

      在您的特定情况下,您应该回答有关您正在更改的内容的问题。

      • 这是你想要/可以一步改变的单一事物
      • 您希望/需要以事务方式更改的不同内容

      如果您将 旧数据库 切换为 新数据库 并将所有内容一起更改以更改单个字段,因此您说您的数据库是 atom,您'正在滥用机制。

      希望区别有所帮助,对于您的示例,我仍然会使用原子。

      每个策略背后都有一个good summary here 的动机。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2012-10-27
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-07-07
        • 2020-10-22
        • 2013-01-17
        相关资源
        最近更新 更多