Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/clojure/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Concurrency 单原子与多参考_Concurrency_Clojure_Stm - Fatal编程技术网

Concurrency 单原子与多参考

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事务都将并行尝试,第一个准备就绪的事

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

例如:

(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"))