使用单个 atom 和 hashmap 与多个 ref 表示状态的权衡是什么?
例如:
(def start (atom {:location "Chicago" :employer "John"}))
对比
(def location (ref "Chicago"))
(def employer (ref "John"))
非常感谢
使用单个 atom 和 hashmap 与多个 ref 表示状态的权衡是什么?
例如:
(def start (atom {:location "Chicago" :employer "John"}))
对比
(def location (ref "Chicago"))
(def employer (ref "John"))
非常感谢
单原子版本更好,并且折衷更少。鉴于您不想更改雇主和不协调的位置,您的胜利是您不必创建dosync
块来更改位置或雇主或两者兼而有之。使用原子,您可以简单地(swap! start assoc :location "baz")
.
使用多个 refs 的一个很大的权衡是所有对 refs 的交易都将被并行尝试,第一个准备好的将获胜,其他的将被重新启动。虽然对于 atom 也是如此,但为所有条目拥有更多的 ref 需要在幕后进行更多的监控、分组(对于 dosync 块)等。为了减少重新启动,将信息分组到哈希图中是有意义的。根据是否需要协调更改,将其放在 ref 或 atom 中。
多个 Ref 允许更多的并发性,因为对 Atom 的所有写入都是线性化的。当没有冲突的写入时,STM 允许提交许多并行事务ensure
(此外,它还提供commute
允许进行某些通常会导致冲突的写入不这样做)。
此外,STM 与代理合作——当且仅当事务提交时,才会执行从事务中发送到代理的操作。这允许人们从交易内部安全地产生副作用。Atoms 没有提供类似的功能。
权衡是 STM 的开销大于 Atom 的开销,而且有可能发生某些异常(写入偏差,请参阅关于快照隔离的 Wikipedia 页面)。此外,在获取整个系统的快照时遇到严重问题时,可以使用 STM 实现出色的并发性;在这方面,请参阅 Christophe Grand 的优秀博客文章和他的megaref库。
在许多情况下,人们发现只需将所有状态存储在单个 Atom 中就足够了,这绝对是一种更简单、更轻量级的方法。
atoms
我认为您不应该考虑在vs.之间进行权衡refs
,因为它们用于不同的情况。
当您想以原子atom
方式更改单个事物时,您应该使用。
refs
使用STM并涉及在事务中同时更改的许多不同事物。
在您的特定情况下,您应该回答有关您正在更改的内容的问题。
如果您将旧数据库切换为新数据库并将所有内容一起更改以更改单个字段,那么您说您的数据库是atom
,那么您正在滥用该机制。
希望区别有所帮助,对于您的示例,我仍然会使用原子。
这里有一个很好的总结,每个策略背后的动机。