the two threads race to acquire the write lock and the winner runs, the loser retries. my guess is acquiring the write lock helps avoid live locks between transactions.
On Mon, Aug 29, 2011 at 10:59 PM, Laurent PETIT <laurent.pe...@gmail.com> wrote: > 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 -- And what is good, Phaedrus, And what is not good— Need we ask anyone to tell us these things? -- 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