My tests were false. Since I sent the code "at once" to the REPL, there was a race condition between the start of the agent and the dosync for setting the ref's value to 2000 ; this explains the weirdness of my test results (thank you, Mr Murphy, for having made the tests look like beta2 behaved differently from the others ...)
So now I see consistent behaviours across 1.2.0, beta1 and beta2. But I am still perplex and confused by the behaviour ... 2011/8/30 Laurent PETIT <laurent.pe...@gmail.com> > ok so now i'm totally confused, since I cannot see why the behaviour is so > different between beta1 and beta 2 ... > > > 2011/8/30 Laurent PETIT <laurent.pe...@gmail.com> > >> 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