这个clojure解决方案是否有睡眠理发师的错误?

时间:2013-05-27 23:49:22

标签: clojure stm

这是sleeping barber problem的解决方案。 (归因于CGrand,但我找到了引用here

yanked from 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 equivalent时想到了这一点,这迫使你在STM内部和STM外部使用不同类型的“代理”。上面的原始解决方案不会编译,因为它们既可以在事务中,也可以在任何事务之外。 (我的第一反应是将它们都放在交易中,直到我意识到不需要这个并且它们都可以被提取出来。)

我认为修改后的交易应该是优越的,因为它可以更快地关闭交易,从交易中删除变量,我认为更容易阅读(甚至不必怀疑它被发送两次的可能性 - 这实际上使整个问题没有实际意义)尽管如此,我还是会留下任何需要知道STM和代理如何互动的人。

1 个答案:

答案 0 :(得分:5)

引用clojure.org page on agents

  

代理与STM集成 - 事务中的任何调度都会一直保留到提交,如果重试或中止,则会被丢弃。

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