未能关闭通道会导致无限期阻塞

时间:2015-05-20 20:21:46

标签: clojure core.async

以下是http://www.braveclojure.com/core-async/的示例:

(defn hotdog-machine-v2 [hotdog-count]
  (let [in (chan) out (chan)]
    (go (loop [hc hotdog-count]
          (if (> hc 0)
            (let [input (<! in)]
              (if (= 3 input)
                (do
                  (>! out "hotdog")
                  (recur (dec hc))  )
                (do
                  (>! out (Exception. "Not enough payment!"))
                  (recur hc))))
            (do
              (close! in)
              (close! out)))))
    [in out]))
(let [[in out] (hotdog-machine-v2 2)]
  (>!! in "pocket lint")
  (println (<!! out))
  (>!! in 3)
  (println (<!! out))
  (>!! in 3)
  (println (<!! out))
  (>!! in 3)
  (println (<!! out))
  )

如果我遗漏了频道关闭部分,那么这段代码会永远挂起,为什么?

1 个答案:

答案 0 :(得分:3)

如果我在正常情况下使用关闭它运行它会打印出来:

user> (let [[in out] (hotdog-machine-v2 2)]
  (>!! in "pocket lint")
  (println (<!! out))
  (>!! in 3)
  (println (<!! out))
  (>!! in 3)
  (println (<!! out))
  (>!! in 3)
  (println (<!! out)))
#error {
 :cause Not enough payment!
 :via
 [{:type java.lang.Exception
   :message Not enough payment!
 ... stack trace here ...

 [java.lang.Thread run Thread.java 724]]}
hotdog
hotdog
nil     ;; <---- look here

最后一个nil是读取值nil的最后一次读取的结果,该值是由于通道关闭而发送的,因为机器没有热狗。没有关闭,最后放置(>!! in 3)块等待从没有人将要做的陈读取的东西。默认情况下写入core.async chans不会写入成功,直到某人准备好阅读该值

如果我取出收盘,取出最后一次写入,则不打印nil,不会阻止:

user> (let [[in out] (hotdog-machine-v2 2)]
  (>!! in "pocket lint")
  (println (<!! out))
  (>!! in 3)
  (println (<!! out))
  (>!! in 3)
  (println (<!! out))
  )
#error {
 :cause Not enough payment!
 :via
 [{:type java.lang.Exception
   :message Not enough payment!
   :at ... stack trace here ...}
hotdog
hotdog