Thanks for your comments. As suggested I ran a small benchmark of both versions. Turns out that the difference between (ref-set ref @ref) and ensure is huge ...
(defn write-skew [de-ref]
(let [cats (ref 1)
dogs (ref 1)
john (future
(dosync
(when (< (+ @cats (de-ref dogs)) 3)
(alter cats inc))))
mary (future
(dosync
(when (< (+ (de-ref cats) @dogs) 3)
(alter dogs inc))))]
(do @john @mary)
(dosync
(> (+ @cats @dogs) 3))))
user> (bench/with-progress-reporting
(bench/bench (write-skew (fn [x] (ref-set x @x))) :verbose))
Warming up for JIT optimisations 10000000000 ...
compilation occurred before 18580 iterations
Estimating execution count ...
Sampling ...
Final GC...
Checking GC...
Finding outliers ...
Bootstrapping ...
Checking outlier significance
amd64 Linux 3.16.0-4-amd64 4 cpu(s)
OpenJDK 64-Bit Server VM 24.121-b00
Runtime arguments: -Dfile.encoding=UTF-8 -XX:+TieredCompilation -XX:TieredStopAtLevel=1 -XX:-OmitStackTraceInFastThrow -Dclojure.compile.path=/home/bertschi/GitRepos/Vorlesungen/PS2/target/classes -Dps2.version=0.0.0 -Dclojure.debug=false
Evaluation count : 1675560 in 60 samples of 27926 calls.
Execution time sample mean : 37,327714 µs
Execution time mean : 37,325021 µs
Execution time sample std-deviation : 1,137506 µs
Execution time std-deviation : 1,147482 µs
Execution time lower quantile : 34,971387 µs ( 2,5%)
Execution time upper quantile : 39,511899 µs (97,5%)
Overhead used : 12,902114 ns
nil
user> (bench/with-progress-reporting
(bench/bench (write-skew ensure)))
Warming up for JIT optimisations 10000000000 ...
compilation occurred before 40 iterations
compilation occurred before 61 iterations
Estimating execution count ...
Sampling ...
Final GC...
Checking GC...
Finding outliers ...
Bootstrapping ...
Checking outlier significance
Evaluation count : 60 in 60 samples of 1 calls.
Execution time mean : 1,662454 sec
Execution time std-deviation : 1,906919 sec
Execution time lower quantile : 186,394000 µs ( 2,5%)
Execution time upper quantile : 7,630998 sec (97,5%)
Overhead used : 12,902114 ns
Found 4 outliers in 60 samples (6,6667 %)
low-severe 2 (3,3333 %)
low-mild 2 (3,3333 %)
Variance from outliers : 98,3142 % Variance is severely inflated by outliers
nil
I'm running clojure 1.8.0 by the way. According to VisualVM the (ref-set ref @ref) version spends most of its time in clojure.lang.LockingTransaction$RetryEx.<init> () while ensure gets basically stuck (> 99%) at clojure.lang.LockingTransaction.tryWriteLock ().