未来内部的 Clojure dosync 与 dosync 内部的未来
Clojure dosync inside future vs future inside dosync
我有如下一段代码
(def number (ref 0))
(dosync (future (alter number inc))) ; A
(future (dosync (alter number inc))) ; B
第二个成功,但第一个失败 no transaction is running
。但它被包裹在一个 dosync 中,对吗?
clojure 是否记得根据创建它的线程打开事务?
你是对的。 dosync
的全部目的是在当前线程中开始一个事务。 future
在新线程中运行其代码,因此 alter
以防 A 不在其线程的 dosync
内。
对于情况 B,alter
和 dosync
都在同一个(新)线程中,所以没有问题。
这不起作用的原因有多种。正如艾伦·汤普森 (Alan Thompson) 所写,事务归属于单个线程,因此当您创建新线程时,您会丢失事务。
另一个问题是 dosync
的动态范围。如果你写
也会出现同样的问题
((dosync #(alter number inc)))
这里我们在 dosync
范围内创建一个函数,并让该函数成为 dosync
的结果。然后我们从dosync
块外调用函数,当然交易不再是运行.
这与您使用 future
所做的非常相似:future
创建一个函数,然后在新线程上执行它,返回一个句柄,您可以使用它来检查该函数的进度线。即使允许跨线程事务,这里也会出现竞争条件:dosync
块是在执行 future
中的 alter
调用之前还是之后关闭其事务?
我有如下一段代码
(def number (ref 0))
(dosync (future (alter number inc))) ; A
(future (dosync (alter number inc))) ; B
第二个成功,但第一个失败 no transaction is running
。但它被包裹在一个 dosync 中,对吗?
clojure 是否记得根据创建它的线程打开事务?
你是对的。 dosync
的全部目的是在当前线程中开始一个事务。 future
在新线程中运行其代码,因此 alter
以防 A 不在其线程的 dosync
内。
对于情况 B,alter
和 dosync
都在同一个(新)线程中,所以没有问题。
这不起作用的原因有多种。正如艾伦·汤普森 (Alan Thompson) 所写,事务归属于单个线程,因此当您创建新线程时,您会丢失事务。
另一个问题是 dosync
的动态范围。如果你写
((dosync #(alter number inc)))
这里我们在 dosync
范围内创建一个函数,并让该函数成为 dosync
的结果。然后我们从dosync
块外调用函数,当然交易不再是运行.
这与您使用 future
所做的非常相似:future
创建一个函数,然后在新线程上执行它,返回一个句柄,您可以使用它来检查该函数的进度线。即使允许跨线程事务,这里也会出现竞争条件:dosync
块是在执行 future
中的 alter
调用之前还是之后关闭其事务?