Welcome! Please see the About page for a little more info on how this works.

0 votes
in Clojure by
The following program demonstrates livelock when using {{ensure}}.


(let [cats (ref 1)
      dogs (ref 1)
      events (atom [])
      john (future
             (dosync
               (swap! events conj :j1)
               (when (< (+ @cats (ensure dogs)) 3)
                 (swap! events conj :j2)
                 (ref-set cats 2))
               (swap! events conj :j3)))
      mary (future
             (dosync
               (swap! events conj :m1)
               (when (< (+ (ensure cats) @dogs) 3)
                 (swap! events conj :m2)
                 (ref-set dogs 2))
               (swap! events conj :m3)))]
  @john @mary @events)
; => [:m1 :j1 :m2 :j2 :j1 :m1 :j2 :m2 :j1 :m1 :j2 :m2 :m1 :j1 :j2 :m2 :m1 :j1 :j2 :m2 :m1 :j1 :m2 :j2 :m1 :j1 :j2 :m2 :j1 :m1 :j2 :m2 :m1 :j1 :m2 :j2 :j1 :m1 :m2 :j2 :m1 :j1 :j2 :m2 :m1 :j1 :m2 :j2 :m1 :j1 :j2 :m2 :m1 :j1 :j2 :m2 :m1 :j1 :j2 :m2 :j1 :m1 :m2 :j2 :m1 :j1 :j2 :m2 :m1 :j1 :m2 :j2 :m1 :j1 :m2 :j2 :j1 :m1 :j2 :m2 :m1 :j1 :m2 :j2 :j1 :m1 :m2 :j2 :m1 :j1 :j2 :m2 :m1 :j1 :m2 :j2 :m1 :m2 :j1 :m3 :j1 :j3]


This program sometimes terminates very quickly, but sometimes there is a delay of several seconds as the transactions are retried dozens or hundreds of times.

{{(ensure ref)}} can exhibit livelock in a way that the equivalent {{(ref-set ref @ref)}} cannot, because only the latter supports barging. With {{ref-set}} older transactions will ultimately win thanks to barging. With {{ensure}} there is no barging as both transactions try to get the write lock ({{ref-set}}) of the ref whose read lock is held by the other transaction ({{ensure}}). Both transactions sit idle for the full 100ms timeout and will then simultaneously retry.

This could be just a doc enhancement. The sentence 'Allows for more concurrency than (ref-set ref @ref)' may not be true generally (and is anyway too vague to be much help). {{(ref-set ref @ref)}} is safer than {{(ensure ref)}}.

2 Answers

0 votes
by

Comment made by: glts

From an old mailing list discussion (link: https://groups.google.com/d/msg/clojure/H676Em2zvhM/oXqKS-OvAgAJ text: here) and (link: https://groups.google.com/d/msg/clojure-dev/OC3N4O1jy9Q/QuH9iYT7DgAJ text: here).

0 votes
by
Reference: https://clojure.atlassian.net/browse/CLJ-2301 (reported by glts)
...