为什么阿尔法会提前停下来,而我希望它表现得像贝塔?阿尔法和贝塔之间唯一的区别是>!和put!,如下所示。
阿尔法:
user=> (def q (chan))
#'user/q
user=> (def counter (atom 0))
#'user/counter
user=> (defn mg [event-queue]
#_=> (go-loop [event (<! event-queue)]
#_=> (swap! counter inc)
#_=> (when (< @counter 4)
#_=> (println "counter: " @counter)
#_=> (>! event-queue {:a @counter}) ;; Here's the only difference
#_=> (println "event: " event)
#_=> (recur (<! event-queue)))))
#'user/mg
user=> (mg q)
#object[clojure.core.async.impl.channels.ManyToManyChannel 0x3a1ffd56 "clojure.core.async.impl.channels.ManyToManyChannel@3a1ffd56"]
user=> (put! q "hi")
counter: true
1
user=>测试版:
user=> (def q (chan))
#'user/q
user=> (def counter (atom 0))
#'user/counter
user=> (defn mg [event-queue]
#_=> (go-loop [event (<! event-queue)]
#_=> (swap! counter inc)
#_=> (when (< @counter 4)
#_=> (println "counter: " @counter)
#_=> (put! event-queue {:a @counter}) ;; Here's the only difference
#_=> (println "event: " event)
#_=> (recur (<! event-queue)))))
#'user/mg
user=> (mg q)
#object[clojure.core.async.impl.channels.ManyToManyChannel 0x72c9b65a "clojure.core.async.impl.channels.ManyToManyChannel@72c9b65a"]
user=> (put! q "hi")
true
counter: 1
event: hi
counter: 2
event: {:a 1}
counter: 3
event: {:a 2}
user=> 同样有趣的是,在执行Alpha之后,通道#'user/q被正确地排队:
user=> (take! q println)
event: hi
{:a 1}
nil
user=> 同样的结果出现在Clojure和Clojurescript中。这是某种类型的死锁,还是应该发生的?
发布于 2015-11-20 17:20:22
这是意料之中的。
通道q是在没有缓冲区的情况下创建的,所以当一个值与>!放在一起时,它将阻塞(停放) go-loop,直到另一个线程准备使用<!来使用该值为止。
解决这一问题的一种方法是给q一个带有(def q (chan 1))的1槽缓冲区。缓冲区允许将1值放置在通道中,而不阻塞发送方。
由于put!是异步wrt,所以Beta的行为有所不同。调用者--它使用一个单独的线程将新值放置在通道中。这样可以避免阻塞当前的go-loop,从而允许读取通道并继续进行。
https://stackoverflow.com/questions/33832040
复制相似问题