Search code examples
multithreadingclojuredynamic-variables

Dynamic var and Thread/sleep


From what I read somewhere, if you bind a new value to a dynamic var in Clojure, that new value is only available in that thread.

So, in order to test that, I created this code:

(def *dynamic-var* "dynamic var")

(defn run-it [] 
  (future (binding [*dynamic-var* "new-value"] (Thread/sleep 3000) (println *dynamic-var*)))
  (future (Thread/sleep 1000) (println *dynamic-var*)))

My question is: why does the first thread (which must print "new-value") never run? It never prints "new-value" to the console.


Solution

  • The issue is that you need to mark your var as dynamic with metadata:

    (def ^:dynamic *dynamic-var* "dynamic var")
    
    (defn run-it [] 
      (future (binding [*dynamic-var* "new-value"] (Thread/sleep 3000) (println *dynamic-var*)))
      (future (Thread/sleep 1000) (println *dynamic-var*)))
    

    With ^:dynamic added, when you run (run-it) it will print out:

    dynamic var
    new-value
    

    Without it you probably saw a warning printed:

    Warning: dynamic-var not declared dynamic and thus is not dynamically rebindable, but its name suggests otherwise. Please either indicate ^:dynamic dynamic-var or change the name.