去通道容量,为什么它需要比我指定的元素多一个

时间:2014-08-28 02:10:43

标签: go channel

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)
     }
}

输出

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

如果我将message := make(chan string ,1) // no buffer更改为

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

我得到了

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

为什么2个缓冲区通道可以存储3个字符串对象?不是2?

感谢,

1 个答案:

答案 0 :(得分:2)

它的工作方式与此类似,因为缓冲区在阻塞之前保存N条消息。当N + 1消息进入GO时,它将看到它超过您指定的容量,并且必须阻止,等待从该通道获取的内容。传递缓冲区大小时,发送方将始终阻止N + 1消息。

例如,对于大小为2,您有一个空缓冲区:

[] []

然后收到一条消息,放入缓冲区:

[M1] []

然后另一个,我们可以继续前进,因为我们在缓冲区中有空格

[M1] [平方米]

然后另一个进来,我们在缓冲区中没有更多的空间,所以我们阻止

[m1] [m2] m3 - &gt;块

像这样。

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

将来我推荐http://golang.org/doc/effective_go.html#channels

var sem = make(chan int, MaxOutstanding)
  

一旦MaxOutstanding处理程序正在执行进程,就会有更多   阻止尝试发送到填充的通道缓冲区,直到其中一个   现有的处理程序完成并从缓冲区接收。