Jos*_*ine 1 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})
Run Code Online (Sandbox Code Playgroud)
所以我有全局var,它由外部值初始化,其他的是计算的,我返回它们的内容.我使用volatile来获得比使用原子更快的速度,而不是每次为每次计算重新定义一个新的var.
问题是这在实践中似乎失败了,因为我map对一个集合(在另一个程序中)做了一些事情,偶尔会对这个函数进行内部子调用,比如(伪代码):
(map
(fn [x]
(let [analysis (do-things x)]
(if blabla
(do-things (f x))
analysis)))) coll)
Run Code Online (Sandbox Code Playgroud)
内部条件调用会在引擎盖下产生另一个线程吗?似乎是的,因为有些人称之为工作,有时则不然.除了在每个do-things身体内部定义挥发物之外还有其他方法吗?
编辑
实际上错误是另一回事,但问题仍然存在:这是一种可接受/安全的方式,没有任何显式调用多线程功能吗?
Clojure中很少有代表你创建线程的结构 - 通常Clojure可以并将在一个或多个线程上运行,具体取决于你的程序结构.pmap是一个很好的示例,可以创建和管理并行映射的线程池.另一个是clojure.core.reducers/fold,它使用fork/join池,但实际上是关于它的.在所有其他情况下,由您来创建和管理线程.
只有在您控制使用范围的情况下才能非常谨慎地使用挥发性物质,以确保您不会与线程竞争以读取和写入相同的挥发性物质.Volatiles保证可以在另一个线程上读取写入,但它们不会保证原子性.为此,您必须使用原子(对于uncoordinated)或refs和STM(对于协调).