Как делают вложенные вызовы dosync ведут себя?

Что происходит, когда Вы создаете вложенные вызовы dosync? Подтранзакции будут завершены в родительском объеме? Действительно ли эти подтранзакции обратимы, если родительская транзакция перестала работать?

13
задан glts 16 August 2019 в 18:10
поделиться

1 ответ

Если вы имеете в виду синтаксическое вложение, то ответ будет , это зависит от того, будет ли внутренний dosync работать на такая же резьба, как и внешняя .

В Clojure всякий раз, когда вводится блок dosync , запускается новая транзакция , если она еще не выполнялась в этом потоке .Это означает, что, хотя выполнение остается в одном потоке, можно сказать, что внутренние транзакции относятся к внешним транзакциям; однако, если dosync занимает позицию, синтаксически вложенную в другой dosync , но запускается в новом потоке, для него будет создана новая транзакция.

Пример, который (надеюсь) иллюстрирует, что происходит:

user> (def r (ref 0))
#'user/r
user> (dosync (future (dosync (Thread/sleep 50) (println :foo) (alter r inc)))
              (println :bar)
              (alter r inc))
:bar
:foo
:foo
1
user> @r
2

«Внутренняя» транзакция повторяет попытку после печати : foo ; «Внешняя» транзакция никогда не требует перезапуска. (Обратите внимание, что после того, как это произойдет, цепочка истории r будет увеличена, поэтому, если "большая" форма dosync была оценена во второй раз, внутренняя dosync ] не будет повторять попытку. Конечно, он все равно не будет объединен с внешним.)

Между прочим, Марк Фолькманн написал фантастическую статью о программной транзакционной памяти Clojure ; это настоятельно рекомендуется прочитать всем, кто заинтересован в глубоком понимании подобных деталей.

18
ответ дан 1 December 2019 в 23:31
поделиться
Другие вопросы по тегам:

Похожие вопросы: