我是 Clojure 的新手,一直在努力了解它的事务模型。
在玩 alter
和 commute
时,我注意到如果我在 commute
之后alter
一个 ref,那么事务不会提交任何内容(或不会更改任何内容)。
例如:
(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,但如果我交换 commute
和 alter
或使用在这种情况下,两个 commute
或两个 alter
将产生所需的结果(分别为 3 和 1)。
我读过一些帖子解释说 commute
和 alter
的行为有点不同,因为 commute
实际上执行了两次一个事务(一个在它所在的位置,另一个在“提交”阶段)并忽略引用的不一致快照。我只是对这两者结合的奇怪行为感到困惑。
谁能帮忙解释一下它是如何工作的?提前致谢!
最佳答案
commute
函数仅在非常狭窄(即罕见)的情况下有用,在这种情况下,它可能以额外的成本减少锁争用重试更新功能。它还使交易的心智模型变得更加复杂,如您的示例所示(例如,我以前从未见过这个特定问题)。
恕我直言,使用 alter
而不是 commute
几乎总是更好,因为 alter
更简单且更可靠。事实上,我通常会将 commute
的使用视为过早优化的一个例子。
关于Clojure:在一个事务中改变之前通勤导致事务失败,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42248836/