猿问

Goroutines 通道和“停止”

我正在阅读/工作Go Concurrency Patterns: Pipelines and cancel,但我无法理解停止短部分。我们有以下功能:


func sq(in <-chan int) <-chan int {

    out := make(chan int)

    go func() {

        for n := range in {

            out <- n * n

        }

        close(out)

    }()

    return out

}


func gen(nums ...int) <-chan int {

    out := make(chan int)

    go func() {

        for _, n := range nums {

            out <- n

        }

        close(out)

    }()

    return out

}

func merge(cs ...<-chan int) <-chan int {

    var wg sync.WaitGroup

    out := make(chan int, 1) // enough space for the unread inputs


    // Start an output goroutine for each input channel in cs.  output

    // copies values from c to out until c is closed, then calls wg.Done.

    output := func(c <-chan int) {

        for n := range c {

            out <- n

        }

        wg.Done()

    }

    wg.Add(len(cs))

    for _, c := range cs {

        go output(c)

    }


    // Start a goroutine to close out once all the output goroutines are

    // done.  This must start after the wg.Add call.

    go func() {

        wg.Wait()

        close(out)

    }()

    return out

}


func main() {

    in := gen(2, 3)


    // Distribute the sq work across two goroutines that both read from in.

    c1 := sq(in)

    c2 := sq(in)


    // Consume the first value from output.

    out := merge(c1, c2)

    fmt.Println(<-out) // 4 or 9

    return

    // Apparently if we had not set the merge out buffer size to 1

    // then we would have a hanging go routine. 

}

现在,如果您注意到 line 2in merge,它表示我们chan使用buffer大小为 1的 out ,因为这是未读输入的足够空间。不过,我几乎可以肯定,我们应该分配chan与buffer大小2.根据此代码示例:


c := make(chan int, 2) // buffer size 2

c <- 1  // succeeds immediately

c <- 2  // succeeds immediately

c <- 3  // blocks until another goroutine does <-c and receives 1 

由于本节意味着一个chan的buffer大小3将不会阻止。任何人都可以澄清/帮助我理解吗?


Smart猫小萌
浏览 167回答 1
1回答

慕工程0101907

程序向通道发送两个值并从通道out读取一个值out。未接收到其中一个值。如果通道没有缓冲(容量 0),那么其中一个发送 goroutine 将阻塞,直到程序退出。这是泄漏。如果创建的通道容量为 1,则两个 goroutine 都可以发送到通道并退出。发送到通道的第一个值由 接收main。第二个值保留在通道中。如果 main 函数没有从 channel 接收到一个值out,那么需要一个容量为 2 的 channel 来防止 goroutines 无限期地阻塞。
随时随地看视频慕课网APP

相关分类

Go
我要回答