Search code examples
multithreadingloopsclojure

Clojure how to get access to one field from two threads?


Can't understand multithreading in clojure. Can't find examples of REAL multithreading. Most samples with atoms, refs, vars are singlethreaded. So, I have a quest. Two threads gaining access to one field, each thread can change it. I use atom for this purpose, so the Code is:

   (do
     (def field (atom "v0"))

     (defn f1 []
       (dotimes [i 100000]
         (if (= i 9999)
           (reset! field "v1"))))

     (defn f2 []
       (dotimes [i 100000]
         (if (= i 777)
           (reset! field "v2"))))

   (do
     (deref (future (Thread/sleep 10) (f1))
            0 f2)
     (prn @field)))

But nothing, the value of field is "v0". How to make normal twothreaded example with cycles in each thread and with access to variable???


Solution

  • watch the docs of deref:

    clojure.core/deref
    ([ref] [ref timeout-ms timeout-val])
    

    returns the in-transaction-value of ref, else returns the most-recently-committed value of ref. When applied to a var, agent or atom, returns its current state. When applied to a delay, forces it if not already forced. When applied to a future, will block if computation not complete. When applied to a promise, will block until a value is delivered. The variant taking a timeout can be used for blocking references (futures and promises), and will return timeout-val if the timeout (in milliseconds) is reached before a value is available. See also - realized?.

    so your timeout is 0, that means it will return default value which is f2 - a function value (not a function call), which is not being called obviously, so no reset! ever happens.

    1. if you want "v1" you should deref like:

      (deref (future (Thread/sleep 10) (f1)) 100 (f2))

    2. if you want "v2":

      (deref (future (Thread/sleep 10) (f1)) 0 (f2))