Wie verhalten sich verschachtelte DoSync Anrufe?
Frage
Was passiert, wenn Sie verschachtelte DoSync Anrufe erstellen? Werden Untertransaktionen im übergeordneten Bereich ergänzt werden? Sind diese Untertransaktionen reversibel, wenn die übergeordnete Transaktion fehlschlägt?
Lösung
Wenn Sie syntaktische Verschachtelung bedeuten, dann ist die Antwort es hängt davon ab, ob der innere dosync
auf dem gleichen Thread wie die äußere läuft .
In Clojure, wann immer ein dosync
Block eingegeben wird, wird eine neue Transaktion gestartet , wenn man auf diesem Thread nicht ausgeführt worden ist bereits . Dies bedeutet, dass während der Ausführung bleibt auf einem einzigen Faden, können innere Transaktionen gesagt werden durch äußere Transaktionen subsumieren; aber wenn ein dosync
eine Position innerhalb eines anderen dosync
syntaktisch verschachtelt einnimmt, sondern geschieht in einem neuen Thread gestartet werden, wird es eine neue Transaktion an sich selbst haben.
Ein Beispiel, das (hoffentlich) zeigt, was passiert:
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
Die „innere“ Transaktion Wiederholungen nach :foo
Druck; die „äußere“ Transaktion muss nie wieder zu starten. (Beachten Sie, dass nach dem dies geschieht, r
Geschichte Kette gewachsen ist, so dass, wenn die „große“ dosync
Form zum zweiten Mal bewertet wurden, wobei die innere dosync
würde Neuversuch nicht. Es wäre immer noch nicht in die Außen eine verschmolzen werden, natürlich. )
Übrigens hat Mark Volkmann einen fantastischen Artikel über Clojure schriftliche Software Transactional Memory ; es ist in hohem Grade für jedermann gewinnen festen Einblick in die Details dieser Art interessiert empfohlen zu lesen.