14

创建嵌套的 dosync 调用时会发生什么?子事务会在父范围内完成吗?如果父事务失败,这些子事务是否可逆?

4

1 回答 1

18

如果您的意思是语法嵌套,那么答案是取决于内部是否dosync与外部运行在同一线程上

在 Clojure 中,每当dosync输入一个块时,如果该线程上尚未运行一个新事务,则会启动一个新事务。这意味着虽然执行停留在单个线程上,但内部事务可以说被外部事务包含;但是,如果 adosync占据了在语法上嵌套在 another中的位置dosync,但恰好是在新线程上启动的,则它自身将有一个新事务。

一个(希望)说明发生了什么的例子:

user> (def r (ref 0))
#'user/r
user> (dosync (future (dosync (Thread/sleep 50) (println :foo) (alter r inc)))
              (println :bar)
              (alter r inc))
:bar
:foo
:foo
1
user> @r
2

“内部”事务在打印后重试:foo;“外部”事务永远不需要重新启动。(请注意,发生这种情况后,的历史链会增长,因此如果第二次评估r“大”表单,则内部不会重试。当然,它仍然不会合并到外部。)dosyncdosync

顺便说一句,Mark Volkmann 写了一篇关于 Clojure 的软件事务内存的精彩文章;强烈推荐任何有兴趣深入了解此类细节的人阅读。

于 2010-05-16T01:13:02.463 回答