使用单个原子和hashmap与多个refs表示状态的权衡是什么?
例如:
(def start (atom {:location "Chicago" :employer "John"}))
VS
(def location (ref "Chicago"))
(def employer (ref "John"))
非常感谢
答案 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)
我认为您不应该考虑在atoms
与refs
之间进行权衡,因为它们会用于不同的情况。
当您想要以原子方式更改 时,您应该使用atom
。
refs
使用STM并在交易中同时更改许多不同的内容。
在你的特殊情况下,你应该回答关于你正在改变的事情的问题。
如果您为新数据库切换旧数据库并将所有内容更改为一个字段,那么您说您的数据库是atom
,你正在滥用这种机制。
希望区别有所帮助,对于你的例子我会尽可能地使用原子。
每种策略背后都有good summary here动机。