原子和参考实际上有何不同?
我理解原子的声明方式不同,并通过swap!
函数更新,而refs在alter
内使用dosync
。 然而,内部实现看起来非常相似,这让我想知道为什么我会使用一个而不是另一个。
例如,atom(http://clojure.org/atoms)的doc页面声明:
在内部,交换!读取当前值,将函数应用于它,并尝试对其进行比较和设置。由于另一个线程可能在中间时间内更改了值,因此可能必须重试,并在旋转循环中执行此操作。实际效果是该值始终是将所提供的函数应用于当前值的结果。但是,因为函数可能被多次调用,所以它必须没有副作用。
所描述的方法听起来与我用于参考的STM非常相似。
答案 0 :(得分:8)
不同之处在于您无法协调多个原子之间的变化,但您可以协调多个参考之间的变化。
参考更改必须在dosync
块内进行。 dosync中的所有更改都会发生,或者它们都不会发生(原子),但会延伸到所有对该dosync中的refs的更改。这与数据库事务非常相似。
例如,假设您要从一个集合中删除一个项目并将其添加到另一个集合中,但没有人看到任何集合都没有该项目的情况。这是不可能用原子保证的,但你可以用refs保证它。
答案 1 :(得分:1)
请记住:
对我来说,我不关心原子和refs之间的实现差异。我关心的是每个人的 “用例” 。
我使用refs,我需要更改多个引用类型的状态,我需要ATM语义。当我改变一个引用类型的状态时,我使用原子(对象,取决于你如何看待它)。
例如,如果我需要增加网络分析系统中的页面点击次数;我用原子。如果我需要在两个账户之间转账,我会使用参考。