Это представлено как решение проблемы спящего парикмахера. (Приписывается 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 и агенты.