Search code examples
multithreadingclojurevolatile

Is clojure "multithread"?


My question may seem weird but I think I'm facing an issue with volatile objects.

I have written a library implemented like this (just a scheme, not real content):

(def var1 (volatile! nil))
(def var2 (volatile! nil))

(def do-things [a]
 (vreset! var1 a)
 (vswap! var2 (inc @var2))
 {:a @var1 :b @var2})

So I have global var which are initialized by external values, others that are calculated and I return their content. i used volatile to have better speed than with atoms and not to redefine everytime a new var for every calculation.

The problem is that this seems to fail in practice because I map do-things to a collection (in another program) with inner sub-calls to this function occasionaly, like (pseudo-code) :

(map 
  (fn [x] 
    (let [analysis (do-things x)] 
      (if blabla 
          (do-things (f x)) 
          analysis)))) coll)

Will inner conditionnal call spawn another thread under the hood ? It seems yes because somethimes calls work, sometimes not. is there any other way to do apart from defining volatile inside every do-things body ?

EDIT

Actually the error was another thing but the question is still here : is this an acceptable/safe way to do without any explicit call to multithreading capabilities ?


Solution

  • There are very few constructs in Clojure that create threads on your behalf - generally Clojure can and will run on one or more threads depending on how you structure your program. pmap is a good example that creates and manages a pool of threads to map in parallel. Another is clojure.core.reducers/fold, which uses a fork/join pool, but really that's about it. In all other cases it's up to you to create and manage threads.

    Volatiles should only be used with great care and in circumstances where you control the scope of use such that you are guaranteed not to be competing with threads to read and write the same volatile. Volatiles guarantee that writes can be read on another thread, but they do nothing to guarantee atomicity. For that, you must use either atoms (for uncoordinated) or refs and the STM (for coordinated).