Clojure代理可以调用​​另一个代理吗?

时间:2011-11-25 16:17:30

标签: concurrency clojure

我最近一直在尝试使用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))
)

2 个答案:

答案 0 :(得分:4)

我不完全确定你要做什么,但函数rr被定义为接受一个参数但是根据

(send (nth readers j) rr (inc j))

它实际上必须采用两个参数(第一个是代理的当前值,第二个参数是(inc j)的值。

表达式(agent-error (first writers))应该显示某种Arity异常(虽然我没有尝试过)

答案 1 :(得分:2)

Clojure代理可以从refsatoms内外发送给其他代理。该功能发送的任何消息都将保留,直到对代理的更改完成为止,因此您不必担心它们会自行竞赛。

代理商的主页上有an example of arranging agents in a ring

在旁注上,如果您从refdosync内发送消息,则保证消息仅在事务提交时发送一次。通常,所有Clojure并发工具都旨在用自己和其他并发工具组合