Congratulations, you've found a bug in clojure 1.3 beta2, see: look with my clojure 1.2.0 version :
;; Clojure 1.2.0 => (def thread (agent "Thread")) (def account (ref 1000)) (send thread (fn [agt aref] (dosync (alter aref + 100) (Thread/sleep 8000) agt)) account) (time (dosync (ref-set account 2000))) #'user/thread #'user/account #<Agent@7e543cb1: "Thread"> "Elapsed time: 0.498106 msecs" 2000 => ;; 10 seconds later : => @account 2100 And now with clojure 1.3 beta1 : ;; Clojure 1.3.0-beta1 => (def thread (agent "Thread")) (def account (ref 1000)) (send thread (fn [agt aref] (dosync (alter aref + 100) (Thread/sleep 8000) agt)) account) (time (dosync (ref-set account 2000))) ;; 10 seconds later : #'user/thread #'user/account #<Agent@6bf51e5c: "Thread"> "Elapsed time: 0.270225 msecs" 2000 => @account 2100 And now with Clojure 1.3-beta2 ;; Clojure 1.3.0-beta2 => (def thread (agent "Thread")) (def account (ref 1000)) (send thread (fn [agt aref] (dosync (alter aref + 100) (Thread/sleep 8000) agt)) account) (time (dosync (ref-set account 2000))) #'user/thread #'user/account #<Agent@50fba502: "Thread"> "Elapsed time: 7957.328798 msecs" 2000 ;; 10 seconds later : => @account 2000 ;; 10 more seconds later : => @account 2000 2011/8/30 Laurent PETIT <laurent.pe...@gmail.com> > 2011/8/29 Dominikus <dominikus.herzb...@gmail.com> > >> Thanks a lot for this detailed analysis and the pointers to the Java >> implementation, Stefan! That's excellent and very helpful. >> >> I still wonder, why the first transaction blocks write access. My >> overall understanding of the transaction system is that changes to >> referenced values remain in-transaction before committing them, a >> write-lock shouldn't be needed. I'm surprised, that the second >> transaction is the one who has to retry 71 times even though the first >> transaction hasn't committed anything yet. >> > > I must confess this behaviour also challenges my assumptions. > > Does this work the same whatever the clojure version used ? > > >> >> Cheers, >> >> Dominikus >> >> P.S.: Thanks for the idea to use 'future' to spawn a thread! >> >> On Aug 29, 5:42 pm, Stefan Kamphausen <ska2...@googlemail.com> wrote: >> > The call to alter already wrote to the Ref, this requires a write-lock >> on >> > the ref (see LockingTransaction.java/doSet). After that it sleeps a >> while >> > and gets to its commit phase. The other transactions retries in the >> > meantime. Consider the following code, which introduces some atoms for >> > counting the retries >> > >> > (defn tz [] >> > (let [rr (ref 10) >> > a1 (atom 0) >> > a2 (atom 0)] >> > (println "Starting future") >> > (future >> > (dosync >> > (swap! a1 inc) >> > (alter rr + 100) >> > (Thread/sleep 8000))) >> > (println "Sleeping a bit") >> > (Thread/sleep 1000) >> > (println "Another dosync") >> > (time >> > (dosync >> > (swap! a2 inc) >> > (ref-set rr 1))) >> > [@rr @a1 @a2 (.getHistoryCount rr)])) >> > >> > user> (tz) >> > Starting future >> > Sleeping a bit >> > Another dosync >> > "Elapsed time: 7001.554 msecs" >> > [1 1 71 0] >> > >> > Note, how the 71 retries nice fit the approximately 7 seconds left and >> the >> > 100 miliseconds time-out (LOCK_WAIT_MSECS) for the lock used in >> > LockingTransaction.java/tryWriteLock. >> > >> > Transactions with significantly different run-times should be avoided, >> > although there is some point at which older transactions will get their >> > turn. This could be another explanation of the effect. Take a look at >> the >> > barge-function in LockingTransaction.java >> > >> > Hope this helps, >> > Stefan >> >> -- >> You received this message because you are subscribed to the Google >> Groups "Clojure" group. >> To post to this group, send email to clojure@googlegroups.com >> Note that posts from new members are moderated - please be patient with >> your first post. >> To unsubscribe from this group, send email to >> clojure+unsubscr...@googlegroups.com >> For more options, visit this group at >> http://groups.google.com/group/clojure?hl=en >> > > -- You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en