“原子交换!”之间的区别和“参考通勤”

时间:2014-03-26 23:49:22

标签: clojure

有什么区别?

1

(def x (ref 0))
(dosync
  (commute x f))

2

(def x (atom 0))
(swap! x f))

这两个例子同样适用

1 个答案:

答案 0 :(得分:8)

如果你只有一个ref和一个原子,那么实际上没有太大区别。我想你可能会了解原子和参考的差异。

commute是一个可以在dosync块中的任何位置调用的函数。 Clojure本身选择何时在此块中执行commute

也许我用一个小例子解释它:

(def x (ref 0))
(def y (ref 0))
(dosync (alter x inc)
        (alter y dec))

alter更改dosync块中ref的值。因为refs是协调和同步的,所以我们需要将它们放在这个块中。如果在更改其中一个ref时发生错误,则整个块都会失败并且您的refs具有与调用更改之前相同的值。

通勤的区别如下:如果我们有以下代码块

(def x (ref 0))
(def y (ref 0))
(dosync (commute x inc)
        (alter y dec))

如果更改refs的值时此处发生错误,则仍会调用commute并更改您的参考号。它不关心alter的结果,即使alter失败,commute也会增加x。 Clojure可以选择何时调用commute,因此即使发生错误也可以执行。

与原子的最大区别在于原子不协调。如果一个原子上有多个swap!,则可能只会执行第一个swap!。我的一个项目遇到了这个问题,我必须确保在调用下一个swap!之前第一个swap!已经终止。

再次:想想你真正需要的东西。你需要一个原子或一些参考?如果你选择refs,你可以选择alter,它在你想要它的位置执行,或commute在哪里Clojure可以决定何时调用它(然后调用可交换)。

如果选择原子,则只能在执行此原子时更改一个值。如果另一个调用尝试swap!该值,则会被拒绝。