【问题标题】:Can Clojure agents invoke another agent?Clojure 代理可以调用​​另一个代理吗?
【发布时间】:2011-11-25 16:17:30
【问题描述】:

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

【问题讨论】:

  • 只是一个旁注,将封闭的括号放在换行符中并不是特别惯用的lisp

标签: concurrency clojure


【解决方案1】:

我不完全确定您要做什么,但函数 rr 被定义为采用一个参数,但根据

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

它实际上应该有两个参数(第一个是代理的当前值,第二个参数是(inc j)的值。

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

【讨论】:

    【解决方案2】:

    Clojure 代理可以发送到refsatoms 内外的其他代理。该函数发送的任何消息都会保留到对代理的更改完成,因此您不必担心它们会与自己竞争。

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

    附带说明,如果您从refdosync 中发送消息,则保证在事务提交时只发送一次消息。一般来说,所有 Clojure 并发工具都旨在与它们自己和其他并发工具组合

    【讨论】:

      猜你喜欢
      • 2013-06-18
      • 1970-01-01
      • 1970-01-01
      • 2021-05-12
      • 2014-04-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-06-23
      相关资源
      最近更新 更多