单原子与多个refs

时间:2013-11-07 14:24:05

标签: concurrency clojure stm

使用单个原子和hashmap与多个refs表示状态的权衡是什么?

例如:

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

VS

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

非常感谢

3 个答案:

答案 0 :(得分:3)

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

使用多个refs的一个重要权衡是所有refs的事务都将并行尝试,第一个准备就绪,其他事务将重新启动。虽然对于原子来说也是如此,但是对于所有条目具有更多ref,需要在幕后进行更多监视,分组(对于dosync块)等。为了减少重启次数,将信息分组到哈希映射中是有意义的。根据是否需要协调变更,将其放在ref或atom中。

答案 1 :(得分:2)

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

此外,STM与代理协作 - 当且仅当事务提交时,才会执行从事务内发送到代理的操作。这允许人们安全地在事务内部引起副作用。 Atoms没有类似的设施。

权衡是STM的开销大于Atom,并且有可能发生某些异常(写入偏斜,请参阅the Wikipedia page on snapshot isolation)。此外,它可以与STM实现良好的并发性,同时在获取整个系统的快照方面存在严重问题;在这方面,请参阅Christophe Grand的优秀blog post和他的megaref图书馆。

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

答案 2 :(得分:1)

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

当您想要以原子方式更改 时,您应该使用atom

refs使用STM并在交易中同时更改许多不同的内容。

在你的特殊情况下,你应该回答关于你正在改变的事情的问题。

  • 是您想要/可以一步改变的一件事
  • 您想要/需要在事务上更改的不同内容

如果您为新数据库切换旧数据库并将所有内容更改为一个字段,那么您说您的数据库是atom ,你正在滥用这种机制。

希望区别有所帮助,对于你的例子我会尽可能地使用原子。

每种策略背后都有good summary here动机。