嵌套的dosync调用如何表现?

Sta*_*ked 13 clojure stm

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

Mic*_*zyk 18

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

在Clojure中,无论何时dosync输入块,如果尚未在此线程上运行,则启动新事务.这意味着当执行保留在单个线程上时,内部事务可以说是由外部事务包含的; 但是如果a dosync占据一个在语法上嵌套在另一个中的位置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
Run Code Online (Sandbox Code Playgroud)

打印后"内部"事务重试:foo; "外部"交易永远不需要重启.(注意,在这种情况发生之后,r历史链会增长,所以如果dosync第二次评估"大" 形式,内部dosync就不会重试.当然,它仍然不会合并到外部.)

顺便提一下,Mark Volkmann写了一篇关于Clojure 软件事务记忆的精彩文章; 对于有兴趣深入了解此类细节的人,强烈建议阅读.