我有下面的代码
(def number (ref 0))
(dosync (future (alter number inc))) ; A
(future (dosync (alter number inc))) ; B第二个成功了,但是第一个no transaction is running失败了。但它是包在卷宗里的,对吧?
clojure还记得基于在哪个线程中创建的事务打开吗?
发布于 2017-11-07 16:08:53
你是对的。dosync的全部目的是在当前线程中开始一个事务。future在一个新线程中运行其代码,因此,如果A不在其线程的dosync中,则alter将不存在。
对于案例B,alter和dosync都在同一个(新的)线程中,所以没有问题。
发布于 2017-11-07 20:31:36
这不起作用的原因有很多。正如Alan所写的,事务被归为单个线程,因此,当您创建一个新线程时,您将丢失事务。
另一个问题是dosync的动态范围。如果你写了同样的问题
((dosync #(alter number inc)))在这里,我们在dosync范围内创建一个函数,并让该函数成为dosync的结果。然后我们从dosync块外部调用函数,但是事务当然不再运行。
这与您使用future所做的非常相似:future创建一个函数,然后在一个新线程上执行它,返回一个句柄,您可以用来检查该线程的进度。即使允许跨线程事务,这里也有一个争用条件:dosync块是在执行future中的alter调用之前还是之后关闭其事务?
https://stackoverflow.com/questions/47162315
复制相似问题