当多个进程等待将数据放在同一个通道中时,是否保证顺序?

时间:2015-05-22 08:27:47

标签: clojure core.async

以下是代码:

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


(def mychan (chan))
(go (while true
      (>! mychan "what is this?")))
(go (loop [i 0]
      (>! mychan (str "msg" i))
      (recur (inc i))))
(go (loop [i 0]
      (>! mychan (str "reply" i))
      (recur (inc i))))
(go (loop [i 0]
      (>! mychan (str "curse" i))
      (recur (inc i))))

repl中的一些实验表明,通道依次从4个过程中的每一个中获取数据:

(<!! mychan)
=> "what is this?"
(<!! mychan)
=> "msg0"
(<!! mychan)
=> "reply0"
(<!! mychan)
=> "curse0"
(<!! mychan)
=> "what is this?"
(<!! mychan)
=> "msg1"
(<!! mychan)
=> "reply1"
(<!! mychan)
=> "curse1"
(<!! mychan)
=> "what is this?"
(<!! mychan)
=> "msg2"
(<!! mychan)
=> "reply2"
(<!! mychan)
=> "curse2"

我想知道订单是否始终保持不变,即首先开始的流程也将在每个周期中首先进入通道。

1 个答案:

答案 0 :(得分:2)

唯一的保证是订单将保留在来自单个go块的消息中。例如,当您从频道中进行阅读时,您将看到来自某个go块的所有消息,其顺序与go块放入频道的顺序相同。但是,这些消息可能与其他作者的消息交织在一起。

在您的特定示例中,顺序似乎是确定性的,但它是由人与REPL的缓慢交互引起的。当您将代码键入或粘贴到REPL时,go块开始竞争通道(并且它们会阻塞,直到有人准备从通道读取)。

作为实验,您可以执行:

(dotimes [n 10000] (println (<!! mychan)))

并检查订单是否相同。在我的REPL中,我得到了例如:

what is this?
msg2507
curse2508
reply2508
what is this?
msg2508
curse2509
reply2509
what is this?

如您所见,curse2509出现在reply2509之前。