dosync executes forms within a Clojure software transactional memory transaction. It coordinates changes to multiple refs without requiring explicit locks, and returns the transaction’s final expression. section 14.4
Coordinating an account transfer
Use alter on both refs so the balance changes belong to one transaction: (transfer 300) returns {:account-1 700, :account-2 800}. section 14.4
Within dosync, common transactional operations include:
- alter and ref-set update ref values. section 14.4
- commute supports concurrent counter-style updates, while ensure protects a ref read. section 14.4
- I/O side effects are rejected inside a transaction. section 14.4
(def account-1 (ref 1000)) ; #1
(def account-2 (ref 500))
(defn transfer [amount]
(dosync ; #2
(when (pos? (- @account-1 amount))
(alter account-1 - amount) ; #3
(alter account-2 + amount))
{:account-1 @account-1 :account-2 @account-2}))
(transfer 300) ; #4
;; {:account-1 700, :account-2 800}
Trace a complete dosync transaction from ref creation through conditional transfer and returned balances. section 14.4
