Concurrency 单原子与多参考
使用单个原子和hashmap表示状态与使用多个引用表示状态的权衡是什么 例如:Concurrency 单原子与多参考,concurrency,clojure,stm,Concurrency,Clojure,Stm,使用单个原子和hashmap表示状态与使用多个引用表示状态的权衡是什么 例如: (def start (atom {:location "Chicago" :employer "John"})) vs 非常感谢单原子版本更好,权衡更少。考虑到您不想更改雇主和不协调的地点,您的成功之处在于您不必创建dosync块来更改地点或雇主或两者。使用atom,您只需(swap!start assoc:location“baz”) 使用多个REF的一个大折衷是,所有REF事务都将并行尝试,第一个准备就绪的事
(def start (atom {:location "Chicago" :employer "John"}))
vs
非常感谢单原子版本更好,权衡更少。考虑到您不想更改雇主和不协调的地点,您的成功之处在于您不必创建
dosync
块来更改地点或雇主或两者。使用atom,您只需(swap!start assoc:location“baz”)
使用多个REF的一个大折衷是,所有REF事务都将并行尝试,第一个准备就绪的事务将获胜,其他事务将重新启动。虽然原子也是如此,但为所有条目提供更多的引用需要在幕后进行更多的监控、分组(对于dosync块)等。为了减少重启次数,可以将信息分组到哈希映射中。根据是否需要协调更改,将其放在ref或atom中。我认为您不应该考虑
原子与参考之间的权衡,因为它们用于不同的情况
当您想要以原子方式更改单个事物时,应该使用原子
refs
在一个事务中同时使用并涉及许多不同的内容
在你的特殊情况下,你应该回答关于你正在改变的事情的问题
- 这是一件你想要/可以一步改变的事情吗
- 您是否希望/需要在交易中更改不同的内容
如果您将旧数据库切换为新数据库,并将所有内容一起更改为单个字段,因此您说您的数据库是一个atom
,那么您滥用了该机制
希望这种区别能有所帮助,但我还是会使用原子作为例子
每种策略背后都有一系列动机。多个引用允许更多的并发性,因为对Atom的所有写入都是线性化的。STM允许在没有冲突写入时提交多个并行事务/确保
s(此外,它还提供了通勤
,允许进行某些写入,而这些写入通常不会导致冲突)
此外,STM与代理协作——当且仅当事务提交时,才会执行从事务中发送给代理的操作。这使得人们可以从事务内部安全地产生副作用。原子没有提供类似的设施
取舍是STM的开销大于原子的开销,再加上可能发生某些异常(写入偏移,请参阅)。此外,在获取整个系统的快照时存在严重问题的同时,可以实现与STM的高度并发;关于这一点,请参阅克里斯托夫·格兰德的《卓越》和他的图书馆
在许多情况下,人们发现仅仅将所有状态存储在一个原子中就足够了,这无疑是一种更简单、更轻量级的方法。+1表示平衡答案,但这让我有点困惑<代码>此外,STM与代理协作——当且仅当事务提交时,才会执行从事务中发送给代理的操作。
-交换atom时不会执行操作吗?这看起来像是无论成功与否都将执行操作。如果您从传递给交换的函数中发送
,则是,每次重试时将重新执行发送
。尝试例如(defa(atom 0))(defag(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,则只会打印一次。
(def location (ref "Chicago"))
(def employer (ref "John"))