Clojure:在一次事务中更改之前通勤导致事务失败

时间:2017-02-15 12:01:08

标签: clojure transactions stm

我是Clojure的新手并且一直在努力了解它的交易模型。 在使用altercommute时,我注意到如果我alter之后的commute引用,那么交易将不会提交任何内容(或者不对任何内容进行任何更改)

例如:

(def counter (ref 0))
(def i (ref 0))
(future (dosync
          (ref-set counter 1)
          (ref-set i 1)
          (commute counter inc)
          (alter counter inc)))

@counter@i都将为0,但如果我交换commutealter或使用两个commute或两个alter在这种情况下,它将产生所需的结果(分别为3和1)。

我读过一些帖子,解释commutealter的行为有点不同,因为commute实际上在交易中执行了两次(其中一个是它所代表的,其他在“提交”阶段)并忽略ref的不一致快照。我只是对这两者组合的奇怪行为感到困惑。

任何人都可以帮忙解释它的工作原理吗?提前谢谢!

1 个答案:

答案 0 :(得分:0)

commute函数仅在非常狭窄(即罕见)的情况下有用, 可能 以额外重试为代价减少锁争用更新功能。它还使得事务的心理模型变得更加复杂,正如您的示例所示(例如,之前我从未见过这个特定问题)。

恕我直言,使用alter代替commute几乎总是更好,因为alter更简单,更具防弹性。实际上,我通常会考虑使用commute作为过早优化的案例