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

标签 clojure transactions stm

我是 Clojure 的新手,一直在努力了解它的事务模型。 在玩 altercommute 时,我注意到如果我在 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,但如果我交换 commutealter 或使用在这种情况下,两个 commute 或两个 alter 将产生所需的结果(分别为 3 和 1)。

我读过一些帖子解释说 commutealter 的行为有点不同,因为 commute 实际上执行了两次一个事务(一个在它所在的位置,另一个在“提交”阶段)并忽略引用的不一致快照。我只是对这两者结合的奇怪行为感到困惑。

谁能帮忙解释一下它是如何工作的?提前致谢!

最佳答案

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

恕我直言,使用 alter 而不是 commute 几乎总是更好,因为 alter 更简单且更可靠。事实上,我通常会将 commute 的使用视为过早优化的一个例子。

关于Clojure:在一个事务中改变之前通勤导致事务失败,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42248836/

相关文章:

clojure - 使用 Clojure reader 忽略未解析的符号

c# - 回滚 C# 中的临时数据库更改

multithreading - 使用线程级内存保护/分页时存在哪些运行时问题?

haskell - 带 fclabel 的 STM

macos - 将 leiningen repl 的结果复制到剪贴板

maven - JVM 上的 Clojure 是否必须使用 Maven?

SQLException - 事务开始/提交不匹配

mysql - 两个索引列上的 SELECT FOR UPDATE 和 WHERE 条件 - 什么是锁定策略?

clojure - 如何使用 clj 工具 AOT 编译单个 clojure 文件? (没有 deps.edn 文件)