Golang:为啥增加缓冲通道的大小会消除我的 goroutine 的输出?

Posted

技术标签:

【中文标题】Golang:为啥增加缓冲通道的大小会消除我的 goroutine 的输出?【英文标题】:Golang: Why does increasing the size of a buffered channel eliminate output from my goroutines?Golang:为什么增加缓冲通道的大小会消除我的 goroutine 的输出? 【发布时间】:2015-12-08 14:03:32 【问题描述】:

我试图理解为什么使通道的缓冲区大小发生较大变化会导致我的代码意外运行。如果缓冲区小于我的输入(100 个整数),则输出符合预期,即 7 个​​ goroutine 每个读取输入的一个子集并在另一个打印它的通道上发送输出。如果缓冲区的大小与输入相同或更大,则我没有输出也没有错误。我是否在错误的时间关闭了频道?我对缓冲区的工作方式有错误的期望吗?或者,别的什么?

package main

import (
    "fmt"
    "sync"
)

var wg1, wg2 sync.WaitGroup

func main() 
    share := make(chan int, 10)
    out := make(chan string)
    go printChan(out)
    for j:= 1; j<=7; j++ 
        go readInt(share, out, j)
    
    for i:=1; i<=100; i++ 
        share <- i
    
    close(share)
    wg1.Wait()
    close(out)
    wg2.Wait()

func readInt(in chan int, out chan string, id int) 
    wg1.Add(1)
    for n := range in 
        out <- fmt.Sprintf("goroutine:%d was sent %d", id, n)
    
    wg1.Done()

func printChan(out chan string)
    wg2.Add(1)
    for l := range out 
        fmt.Println(l)
    
    wg2.Done()

要运行这个: 小缓冲区,预期输出。 http://play.golang.org/p/4r7rTGypPO 大缓冲区,没有输出。 http://play.golang.org/p/S-BDsw7Ctu

【问题讨论】:

【参考方案1】:

这与缓冲区的大小没有直接关系。添加缓冲区会暴露你调用waitGroup.Add(1)的地方的错误

你必须添加到WaitGroupbefore你调度goroutine,否则你可能最终调用Wait()beforewaitGroup.Add(1)执行。 p>

http://play.golang.org/p/YaDhc6n8_B

它在第一个而不是第二个中起作用的原因是因为同步发送确保 gouroutines 至少执行了那么远。在第二个示例中,for 循环填满了通道,将其关闭并在其他任何事情发生之前调用 Wait。

【讨论】:

以上是关于Golang:为啥增加缓冲通道的大小会消除我的 goroutine 的输出?的主要内容,如果未能解决你的问题,请参考以下文章

Golang 缓冲通道在发送之前接收数据

Golang通道的无阻塞读写的方法示例

golang runtime源码阅读 channal实现

golang runtime源码阅读 channal实现

为啥在同一个 goroutine 中使用无缓冲通道会导致死锁?

在 golang 中创建一片缓冲通道