go 块无限期挂起 core.sync
go block hangs indefinitely with core.sync
代码如下:
(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")
您只会从回显缓冲区中获取第一条消息,并且由于缓冲区大小为 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")
代码如下:
(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")
您只会从回显缓冲区中获取第一条消息,并且由于缓冲区大小为 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")