我最近一直在尝试使用Clojure的多线程功能,并尝试实现一个简单的并发问题。在下面的代码中,我使用一个代理程序运行函数write并尝试将作业发送到另一个代理程序,但程序在此行阻止:
(doseq [j (range (count readers))]
(send (nth readers j) rr (inc j)))
完整代码:
(def state (ref 0))
(def readers (doall (map #(agent %) (repeat 3 0))))
(def writers (doall (map #(agent %) (repeat 3 0))))
(defn rr [re]
(println (format "Read about %s" @state))
(inc re)
)
(defn write [re topic]
(dosync
(ref-set state topic)
)
(Thread/sleep (rand-int 1000))
(println "Wrote about" topic)
(doseq [j (range (count readers))]
(send (nth readers j) rr (inc j)))
(inc re)
)
(defn -main[]
(dotimes [i 5]
(doseq [j (range (count writers))]
(send (nth writers j) write (inc j))))
(dorun (map #(await %) writers))
(dorun (map #(println "Writes:" @%) writers))
)
答案 0 :(得分:4)
我不完全确定你要做什么,但函数rr
被定义为接受一个参数但是根据
(send (nth readers j) rr (inc j))
它实际上必须采用两个参数(第一个是代理的当前值,第二个参数是(inc j)
的值。
表达式(agent-error (first writers))
应该显示某种Arity异常(虽然我没有尝试过)
答案 1 :(得分:2)
Clojure代理可以从refs
和atoms
内外发送给其他代理。该功能发送的任何消息都将保留,直到对代理的更改完成为止,因此您不必担心它们会自行竞赛。
代理商的主页上有an example of arranging agents in a ring
在旁注上,如果您从ref
和dosync
内发送消息,则保证消息仅在事务提交时发送一次。通常,所有Clojure并发工具都旨在用自己和其他并发工具组合