Есть ли ошибка в этом решении clojure для спящего парикмахера?

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


person Dax Fohl    schedule 27.05.2013    source источник


Ответы (1)


Цитирую страницу clojure.org об агентах:

Агенты интегрированы с STM — любые отправки, сделанные в транзакции, удерживаются до тех пор, пока она не будет зафиксирована, и отбрасываются, если она повторяется или прерывается.

Таким образом, send-off запустится только один раз, когда (/если) транзакция STM будет успешно зафиксирована.

person mange    schedule 27.05.2013
comment
Означает ли это, что транзакция остается открытой на протяжении всего периода стрижки? И значит ли это, что dosync в cut-hair не нужен? - person Dax Fohl; 28.05.2013
comment
Если транзакция остается открытой все это время, не означает ли это, что будет накапливаться огромное количество неудачных/повторных транзакций? - person Dax Fohl; 28.05.2013
comment
@DaxFohl Действие send-off будет выполняться после фиксации транзакции, а не во время нее. cut-hair будет добавлен в очередь агента только после фиксации транзакции, затем в какой-то неуказанный момент в будущем cut-hair будет запущен агентом. dosync в cut-hair необходим, потому что cut-hair не выполняется в транзакции. - person mange; 28.05.2013
comment
Круто, теперь все понятно. Гораздо легче следовать, чем эквивалентное решение Актера или решение на основе блокировки, когда вы понимаете грамматику. - person Dax Fohl; 28.05.2013