Angenommen, Sie haben einige Bankkonten:
(def accounts
[(ref 0)
(ref 10)
(ref 20)
(ref 30)])
Und eine atomare "Transfer" -Funktion:
(defn transfer [src-account dest-account amount]
(dosync
(alter dest-account + amount)
(alter src-account - amount)))
Welches funktioniert wie folgt:
(transfer (accounts 1) (accounts 0) 5)
(map deref accounts)
=> (5 5 20 30)
Sie können dann die Übertragungsfunktion einfach zusammenstellen, um eine Transaktion auf höherer Ebene zu erstellen, z. B. die Übertragung von mehreren Konten:
(defn transfer-from-all [src-accounts dest-account amount]
(dosync
(doseq [src src-accounts]
(transfer src dest-account amount))))
(transfer-from-all
[(accounts 0) (accounts 1) (accounts 2)]
(accounts 3)
5)
(map deref accounts)
=> (0 0 15 45)
Beachten Sie, dass alle Mehrfachübertragungen in einer einzigen kombinierten Transaktion stattfanden, dh es war möglich, die kleineren Transaktionen zu "komponieren".
Dies mit Sperren zu tun, würde sehr schnell kompliziert werden: Wenn die Konten einzeln gesperrt werden müssten, müssten Sie beispielsweise ein Protokoll für die Reihenfolge der Sperrenerfassung erstellen, um Deadlocks zu vermeiden. Es ist sehr leicht, einen schwer zu erkennenden Fehler zu machen. STM bewahrt Sie vor all diesen Schmerzen.