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

Is order guaranteed when multiple processes are waiting to put data in the same channel?

代码如下:

(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"

我想知道顺序是否始终保持不变,即在每个周期中,先启动的进程也会先馈送到通道。

唯一的保证是顺序将保留在来自单个 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 之前。