缓冲通道是否保持顺序?

huangapple go评论103阅读模式
英文:

Do buffered channels maintain order?

问题

在Go语言中,带缓冲的通道是否有任何顺序保证?

例如:
你有两个共享通道的goroutine A和B。A将数据推送到通道,而B从通道中读取数据。你能保证B会按照A放入通道的顺序读取数据吗?

我理解如果有多个生产者或消费者,顺序可能是不确定的,但我特别询问的是只有一个生产者和一个消费者的情况。

英文:

In Go, do buffered channels have any order guarantee?

For example:
you have two goroutines A & B that share a channel. A pushes data onto the channel while B reads from it. Are you guranted that B will read data In the same order that A put it into the channel?

I understand that if there are multiple producers or consumers the order may be non-deterministic, but I'm specifically asking about having just 1 producer and 1 consumer.

答案1

得分: 54

你能保证B会按照A放入通道的顺序读取数据吗?

是的,数据的顺序是有保证的。
但是只有对于非缓冲通道,才能保证传递的顺序,而对于缓冲通道则不行。
(请参阅答案的第二部分)

你可以在William Kennedy(2014年2月)的《Go语言通道的本质》一文中看到通道的概念,其中展示了读写的顺序是如何被尊重的。
还可以参考《Go语言文档》中的《通道》一节:

  • 接收者总是阻塞,直到有数据可接收。
  • 如果通道是非缓冲的,发送者会阻塞,直到接收者接收到值。
  • 如果通道是缓冲的,发送者只会阻塞,直到值被复制到缓冲区;如果缓冲区已满,这意味着等待某个接收者取走一个值。

非缓冲通道示意图:

缓冲通道是否保持顺序?

缓冲通道示意图:

缓冲通道是否保持顺序?

(图片来源:Ardan labs - William Kennedy)

同样的,William Kennedy在2017年10月的《通道的行为》一文中详细介绍了传递保证方面的内容。

  • 如果你需要确保特定goroutine发送的信号已被接收,可以选择以下三种通道选项:非缓冲通道、缓冲大小大于1的通道或缓冲大小等于1的通道。

  • 保证

    • 非缓冲通道可以给你一个保证,即发送的信号已被接收。
      • 因为信号的接收发生在发送完成之前
  • 无保证

    • 缓冲大小大于1的通道无法保证发送的信号已被接收。
      • 因为信号的发送发生在接收完成之前
  • 延迟保证

    • 缓冲大小等于1的通道可以给你一个延迟保证。它可以保证前一个发送的信号已被接收。
      • 因为第一个信号的接收发生在第二个信号的发送完成之前
英文:

> "Are you guaranteed that B will read data In the same order that A put it into the channel?"

Yes. The order of data is guaranteed.
But the delivery is guaranteed only for unbuffered channels, not buffered.
(see second section of this answer)


You can see the idea of channels illustrated in "The Nature Of Channels In Go" from William Kennedy (Feb. 2014): it shows how the order or read/write is respected.
See also Channels:

> Receivers always block until there is data to receive.

> - If the channel is unbuffered, the sender blocks until the receiver has received the value.

  • If the channel has a buffer, the sender blocks only until the value has been copied to the buffer; if the buffer is full, this means waiting until some receiver has retrieved a value.

Unbuffered Channels

缓冲通道是否保持顺序?

Buffered Channel

缓冲通道是否保持顺序?

<sup>Image source: Ardan labs - William Kennedy</sup>


The same William Kennedy details the Guarantee Of Delivery aspect in "The Behavior Of Channels" (Oct 2017)

> Do I need a guarantee that the signal sent by a particular goroutine has been received?

缓冲通道是否保持顺序?

<sup>Image source: Again, Ardan labs - William Kennedy</sup>

> The three channel options are Unbuffered, Buffered >1 or Buffered =1.

> - Guarantee

  • An Unbuffered channel gives you a Guarantee that a signal being sent has been received.
    • Because the Receive of the signal Happens Before the Send of the signal completes.

> - No Guarantee
- A Buffered channel of size >1 gives you No Guarantee that a signal being sent has been received.
- Because the Send of the signal Happens Before the Receive of the signal completes.

> - Delayed Guarantee
- A Buffered channel of size =1 gives you a Delayed Guarantee. It can guarantee that the previous signal that was sent has been received.
- Because the Receive of the First Signal, Happens Before the Send of the Second Signal completes.

huangapple
  • 本文由 发表于 2014年9月12日 02:57:34
  • 转载请务必保留本文链接:https://go.coder-hub.com/25795131.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定