これは、睡眠中の床屋の問題に対する解決策として提示されています。(CGrandに起因しますが、参照はこちらで見つかりました)
dosync
のブロックが気になりますenter-the-shop
。私の理解では、これはトランザクションであり、empty-seats
STM により一貫性が保たれます。send-off
しかし、トランザクションがリトライされると、複数回呼び出される可能性はありませんか? そうでない場合、その理由は何ですか? もしそうなら、どのように解決しますか?
アップデート
受け入れられた答えはまだ正しいですが、私が気づいたことの 1 つは、実行できる最適化があること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 外の「エージェント」に異なるタイプを使用することが強制されます。上記の元のソリューションは、両方がトランザクション内にあるか、トランザクション外にある必要があるため、コンパイルされません。(私の最初の反応は、トランザクション内に両方を入れることでしたが、これが必要ではなく、両方を抽出できることに気付くまで)。
変更されたトランザクションは、トランザクションをより速く閉じ、トランザクションから変数を削除し、読みやすいという点で優れていると思います (トランザクションが 2 回送信される可能性について考える必要さえありません。この質問全体は意味がありません) それでも、STM とエージェントがどのように相互作用するかについて知る必要がある他の人のために、とにかく質問を残しておきます.