clojure "multithread" 是吗?

Is clojure "multithread"?

我的问题可能看起来很奇怪,但我认为我遇到了 volatile 个对象的问题。

我写过一个这样实现的库(只是一个方案,不是真正的内容):

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

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

所以我有全局变量,它们由外部值初始化,其他的是计算出来的,我 return 它们的内容。 我使用 volatile 的速度比使用 atoms 的速度更快,而不是每次都为每次计算重新定义一个新的 var。

问题是这似乎在实践中失败了,因为我 map 对一个集合(在另一个程序中)做事,偶尔会对该函数进行内部子调用,比如(伪代码):

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

内部条件调用会在幕后产生另一个线程吗?似乎是的,因为有时称为工作,有时不是。 除了在每个 do-things 体内定义 volatile 之外,还有其他方法吗?

编辑

实际上错误是另一回事,但问题仍然存在:这是一种 acceptable/safe 无需显式调用多线程功能的方法吗?

Clojure 中很少有代表您创建线程的构造 - 通常 Clojure 可以并且将会 运行 在一个或多个线程上,具体取决于您如何构建程序。 pmap 是一个很好的例子,它创建和管理线程池以并行映射。另一个是 clojure.core.reducers/fold,它使用 fork/join 池,但仅此而已。在所有其他情况下,由您来创建和管理线程。

Volatiles 应该 非常小心地使用,并且在你控制使用范围的情况下保证你不会与线程竞争读取和写入相同的内容易挥发的。 Volatiles 保证写入可以在另一个线程上读取,但它们不保证原子性。为此,您必须使用 atoms(对于未协调的)或 refs 和 STM(对于协调的)。