2017-11-07 9 views
0

Ich habe das folgende Stück CodeClojure DoSync innen Zukunft vs Zukunft innerhalb DoSync

(def number (ref 0)) 

(dosync (future (alter number inc))) ; A 
(future (dosync (alter number inc))) ; B 

Die 2. gelingt es, aber die erste scheitern sollte mit no transaction is running. Aber es ist in einem dosync Recht verpackt?

Erinnert sich clojure an das Öffnen von Transaktionen basierend darauf, in welchem ​​Thread es erstellt wurde?

Antwort

2

Sie haben Recht. Der ganze Zweck von dosync ist, eine Transaktion im aktuellen Thread zu beginnen. Die future führt ihren Code in einem neuen Thread, so dass die alter in Fall A nicht innerhalb einer dosync für seinen Thread ist.

Für den Fall B sind die alter und dosync beide im selben (neuen) Thread, also gibt es kein Problem.

2

Es gibt mehrere Gründe, warum dies nicht funktioniert. Wie Alan Thompson schreibt, werden Transaktionen mit einem einzelnen Thread verknüpft. Wenn Sie also einen neuen Thread erstellen, verlieren Sie Ihre Transaktion. Ein anderes Problem ist der dynamische Bereich von dosync. Das gleiche Problem würde sich ergeben, wenn Sie

((dosynC#(alter number inc))) 

Hier schrieben wir eine Funktion innerhalb des dosync Rahmen schaffen, und lassen Sie diese Funktion das Ergebnis der dosync sein. Dann rufen wir die Funktion von außerhalb des dosync Blocks auf, aber natürlich läuft die Transaktion nicht mehr.

Das ist sehr ähnlich zu dem, was Sie tun mit future: future erstellt eine Funktion und führt es dann auf einen neuen Thread, einen Griff zurück, mit dem Sie den Fortschritt dieses Threads überprüfen können. Selbst wenn Cross-Thread-Transaktionen erlaubt wären, hätten Sie hier eine Wettlaufsituation: Schließt der dosync Block seine Transaktion, bevor oder nachdem der alter Aufruf in der future ausgeführt wird?

Verwandte Themen