2015-05-20 2 views
1

Вот код:идут блок виснет на неопределенный срок с 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") 

Это висит навсегда после печати msg1 в nrepl:

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 [email protected]> 
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") 

ответ

4

Вы только когда-либо получать первое сообщение из эхо-буфера, а так как размер буфера равен 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")