Created
January 7, 2016 18:24
-
-
Save bvandgrift/8e0e58463efda84f44ac to your computer and use it in GitHub Desktop.
placing your peek inside of a dosync avoids potential thread conflict (from Clojure Applied forum)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
;; response to: https://forums.pragprog.com/forums/352/topics/13835 | |
;; this is a quick demonstration of the pitfalls in querying for a ref | |
;; outside of the accompanying transaction in which you plan on changing it. | |
(import '(java.util.concurrent Executors)) | |
;; start list | |
(def slist (ref #{})) | |
;; end list | |
(def elist (ref [])) | |
;; initialize the lists | |
(defn init-lists[] | |
(dosync | |
(ref-set slist (into #{} (range 50))) | |
(ref-set elist []))) | |
(init-lists) | |
;; let outside of a dosync block invites | |
;; problems | |
(defn move-item [] | |
(let [i (first @slist)] | |
(dosync | |
(Thread/sleep (rand 100)) | |
(if i | |
(do | |
(alter elist conj i) | |
(alter slist disj i)))))) | |
;; invoke a number of threads to execute moves | |
(defn test-moves [nthreads f] | |
(init-lists) | |
(let [pool (Executors/newFixedThreadPool nthreads)] | |
(dotimes [n 100] ;; account for duplicates | |
(.submit pool f)) | |
(.shutdown pool) | |
(while (not (.isTerminated pool)) (Thread/sleep 500)))) | |
;; moving the let inside the dosync block | |
;; fixes this problem, as the transaction maintains | |
;; the integrity of slist throughout | |
(defn move-item2 [] | |
(dosync | |
(let [i (first @slist)] | |
(Thread/sleep (rand 100)) | |
(if i (do | |
(alter elist conj i) | |
(alter slist disj i)))))) | |
;; use 10 threads, takes ~3 secs on my box | |
(time (test-moves 10 move-item)) | |
;; witness the duplication | |
(sort @elist) | |
;; takes ~8 seconds | |
(time (test-moves 10 move-item2)) | |
;; and now ... | |
(sort @elist) | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment