假设下面的代码中的ref在其他事务以及下面的事务中都被修改,则我担心的是,该事务将一直运行到提交,提交失败,然后重新运行该事务为止。
(defn modify-ref [my-ref]
(dosync (if (some-prop-of-ref-true @my-ref)
(alter my-ref long-running-calculation))))
这是我的全部恐惧:
这就是我想发生的事情,也许这就是发生的事情(我只是不知道,所以我要问一个问题:-)
当事务B提交my-ref时,我希望事务A立即停止(因为my-ref的值已更改)并使用新值重新启动。那会发生什么吗?
我想要这种行为的原因是,长时间运行的计算不会浪费所有CPU时间在现在已过时的计算上。
我曾考虑过使用ensure
,但不知道如何在这种情况下或是否有必要使用它。
它像您担心的那样工作。
停止JVM中的线程做任何事情都需要协作,因此Clojure(或任何其他JVM语言)没有通用的方法来停止正在运行的计算。计算必须定期检查信号以查看其是否应自行停止。请参阅如何杀死Java中的线程?。
关于如何实现它,我会说太难了,因此我首先要衡量它是否真的是一个问题。如果是这样,我会看看传统的悲观锁是否是更好的解决方案。如果悲观锁仍然不是解决方案,我将尝试构建一些在事务外部运行计算的东西,在refs上使用观察程序,并在计算后有条件地设置refs(如果它们仍然具有相同的值)。当然,这超出了交易范围,听起来可能要棘手得多。
关于ensure
,只有被修改的ref才能参与事务,因此您可能会因写入歪斜而受苦。有关详细说明,请参见Clojure STM模糊度因子。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句