clojure是“多线程”吗?

时间:2017-02-08 14:02:47

标签: multithreading clojure volatile

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

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

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

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

所以我有全局var,它由外部值初始化,其他的是计算的,我返回它们的内容。 我使用volatile来获得比使用原子更快的速度,而不是每次为每次计算重新定义一个新的var。

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

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

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

编辑

实际上错误是另一回事,但问题仍然存在:这是一种可接受/安全的方式,没有任何显式调用多线程功能吗?

1 个答案:

答案 0 :(得分:9)

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

Volatiles只能

Volatiles保证可以在另一个线程上读取写入,但它们不会保证原子性。为此,您必须使用原子(对于uncoordinated)或refs和STM(对于协调)。