4

这是作为睡眠理发师问题的解决方案提出的。(归因于CGrand,但我在这里找到了参考)

从cgrand被拉出来

我很dosync好奇enter-the-shop. 我的理解是,这是一个交易,因此empty-seats会因为 STM 而保持一致。但是,如果事务被重试,是不是有可能send-off被多次调用?如果不是,为什么,如果是,如何解决?

更新

虽然接受的答案仍然是正确的,但我刚刚注意到的一件事是可以进行优化——没有理由send-off在事务内部调用。一旦你有了交易的返回值,就可以事后发送,如下:

(if (dosync
       (when (pos? @empty-seats)
         (alter empty-seats dec)))
    (send-off barber cut-hair n)
    (debug "(s) turning away customer" n))

有趣的是,我在处理Haskell 等效项时发现了这一点,这迫使您在 STM 内部和 STM 外部使用不同类型的“代理”。上面的原始解决方案无法编译,因为它们必须要么都在事务中,要么都在任何事务之外。(我的第一反应是将它们都放入事务中,直到我意识到没有必要这样做并且它们都可以被提取)。

我认为修改后的事务应该更好,因为它可以更快地关闭事务,从事务中删除一个变量,并且我认为更容易阅读(甚至不需要怀疑它被发送两次的可能性——这实际上使得这整个问题没有实际意义)不过,无论如何,我还是把这个问题留给任何需要了解 STM 和代理如何交互的人。

4

1 回答 1

5

引用代理上的 clojure.org 页面

代理与 STM 集成 - 在事务中进行的任何分派都将保留到它提交,如果重试或中止,则将其丢弃。

因此send-off,当 (/if) STM 事务成功提交时,它只会运行一次。

于 2013-05-27T23:59:22.243 回答