go block使用core.sync无限期挂起

时间:2015-05-20 16:42:16

标签: asynchronous clojure core.async

以下是代码:

(ns typed-clj-test.async
  (:require [clojure.core.async
             :as a
             :refer [>! <! >!! <!!
                     go chan buffer
                     close! thread
                     alts! alts!! timeout]]))

(def echo-buffer (chan 2))
(go (do (<! (timeout 5000))
        (println (<! echo-buffer))))
(>!! echo-buffer "msg1")
(>!! echo-buffer "msg2")
(>!! echo-buffer "msg3")
(>!! echo-buffer "msg4")

在nrepl中打印msg1后,它会永远挂起:

typed-clj-test.async=> (def echo-buffer (chan 2))
#'typed-clj-test.async/echo-buffer
typed-clj-test.async=> (go (do (<! (timeout 5000))
                  #_=>         (println (<! echo-buffer))))
#<ManyToManyChannel clojure.core.async.impl.channels.ManyToManyChannel@6cc648a>
typed-clj-test.async=> (>!! echo-buffer "msg1")
true
typed-clj-test.async=> (>!! echo-buffer "msg2")
true
typed-clj-test.async=> (>!! echo-buffer "msg3")
msg1
true
typed-clj-test.async=> (>!! echo-buffer "msg4")

1 个答案:

答案 0 :(得分:4)

您只能从echo-buffer中获取第一条消息,并且由于缓冲区大小为2,因此尝试向缓冲区添加第四条消息将阻塞,直到从缓冲区中删除另一条值(永远不会发生。)

换句话说,你似乎期待

(go (do (<! (timeout 5000))
        (println (<! echo-buffer))))

循环,但它不会。

以下是如何使其发挥作用:

(def echo-buffer (chan 2))
(go (do (loop [i 0]
          (<! (timeout (* 100 (rand-int 20))))
          (println (<! echo-buffer))
          (recur i))))
(>!! echo-buffer "msg1")
(>!! echo-buffer "msg2")
(>!! echo-buffer "msg3")
(>!! echo-buffer "msg4")
相关问题