原子如何与refs不同?

时间:2013-08-09 15:41:23

标签: concurrency clojure stm

原子和参考实际上有何不同?

我理解原子的声明方式不同,并通过swap!函数更新,而refs在alter内使用dosync然而,内部实现看起来非常相似,这让我想知道为什么我会使用一个而不是另一个。

例如,atom(http://clojure.org/atoms)的doc页面声明:

  
    

在内部,交换!读取当前值,将函数应用于它,并尝试对其进行比较和设置。由于另一个线程可能在中间时间内更改了值,因此可能必须重试,并在旋转循环中执行此操作。实际效果是该值始终是将所提供的函数应用于当前值的结果。但是,因为函数可能被多次调用,所以它必须没有副作用。

  

所描述的方法听起来与我用于参考的STM非常相似。

2 个答案:

答案 0 :(得分:8)

不同之处在于您无法协调多个原子之间的变化,但您可以协调多个参考之间的变化。

参考更改必须在dosync块内进行。 dosync中的所有更改都会发生,或者它们都不会发生(原子),但会延伸到所有对该dosync中的refs的更改。这与数据库事务非常相似。

例如,假设您要从一个集合中删除一个项目并将其添加到另一个集合中,但没有人看到任何集合都没有该项目的情况。这是不可能用原子保证的,但你可以用refs保证它。

答案 1 :(得分:1)

请记住:

  • 使用Refs进行同步,协调和共享更改。
  • 使用Atom进行同步,独立和共享更改。

对我来说,我不关心原子和refs之间的实现差异。我关心的是每个人的 “用例”

我使用refs,我需要更改多个引用类型的状态,我需要ATM语义。当我改变一个引用类型的状态时,我使用原子(对象,取决于你如何看待它)。

例如,如果我需要增加网络分析系统中的页面点击次数;我用原子。如果我需要在两个账户之间转账,我会使用参考。