Go语言中的通道(channel)容量为什么比我指定的元素数量多一个?

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

go channel capacity ,why does it take one more elements than I specified

问题

这是一个关于Go语言中通道缓冲区的问题。在你的代码中,message := make(chan string, 2)创建了一个具有2个缓冲区的通道。这意味着在发送消息到通道之前,通道可以存储最多2个字符串对象。

在第一个例子中,你的代码循环3次发送消息到通道,但由于通道没有缓冲区,每次发送都会阻塞,直到有一个接收者准备好接收消息。因此,第一个发送操作会成功,但第二个和第三个发送操作会阻塞,直到有接收者接收消息。

在第二个例子中,由于通道有2个缓冲区,前两个发送操作可以立即成功,因为通道有足够的空间来存储这两个消息。第三个发送操作会阻塞,直到有接收者接收消息。

总结起来,通道的缓冲区大小决定了在没有接收者的情况下可以发送到通道的消息数量。如果通道没有缓冲区或缓冲区已满,发送操作将会阻塞,直到有接收者准备好接收消息。

希望这可以解答你的问题!如果还有其他疑问,请随时提问。

英文:
package main
import "fmt"
import "time"

func main() {
     message := make(chan string ,1) // no buffer
     count := 3

     go func() {
          for i := 1; i <= count; i++ {
               fmt.Println("send message")
               message <- fmt.Sprintf("message %d", i)
          }
     }()

     time.Sleep(time.Second * 3)

     for i := 1; i <= count; i++ {
          fmt.Println(<-message)
     }
}

The output is

send message
send message  [wait for 3 sec]
message 1
send message
message 2
message 3

If I change message := make(chan string ,1) // no buffer to

message := make(chan string ,2) // no buffer

I got

send message
send message
send message [wait 3 sec]
message 1
message 2
message 3

Why 2 buffers channel can store 3 string objects? not 2?

thanks,

答案1

得分: 4

这是因为缓冲区在阻塞之前可以容纳N个消息。当第N+1个消息到达时,GO会发现它超过了你指定的容量,必须阻塞等待有人从该通道中取走消息。当传递缓冲区大小时,发送者始终会在第N+1个消息上阻塞。

例如,如果缓冲区大小为2,则开始时缓冲区为空:

[][]

然后有一条消息进来,放入缓冲区:

[m1][]

然后又来一条消息,我们可以继续添加,因为缓冲区有空间:

[m1][m2]

然后又来一条消息,哎呀,缓冲区没有更多空间了,所以我们阻塞了:

[m1][m2]m3 -> 阻塞

就是这样。

缓冲区的大小基本上是可以发送到缓冲区而不阻塞的消息数量。

对于将来,我建议参考http://golang.org/doc/effective_go.html#channels

var sem = make(chan int, MaxOutstanding)

> 一旦有MaxOutstanding个处理程序正在执行过程中,任何多余的处理程序都将阻塞,尝试发送到已满的通道缓冲区,直到其中一个现有处理程序完成并从缓冲区接收。

英文:

It works like this because the buffer holds N messages before it blocks. When the N+1 messages comes in GO will see that it exceeds the capacity you specified and will have to block, waiting for something to take from that channel. When passing a buffer size the sender will always block on N+1 message.

So for instance with size 2 you have an empty buffer:

[][]

Then a message comes in, is put in the buffer:

[m1][]

Then another one, we can keep on going because we have space in the buffer

[m1][m2]

Then another comes in, ups we don't have more space in the buffer so we block

[m1][m2]m3 -> block

Something like this.

The size is basically the number of messages that can be sent to the buffer without blocking.

For the future I recommend http://golang.org/doc/effective_go.html#channels

var sem = make(chan int, MaxOutstanding)

> Once MaxOutstanding handlers are executing process, any more will
> block trying to send into the filled channel buffer, until one of the
> existing handlers finishes and receives from the buffer.

huangapple
  • 本文由 发表于 2014年8月28日 10:10:42
  • 转载请务必保留本文链接:https://go.coder-hub.com/25539649.html
匿名

发表评论

匿名网友

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

确定