一个关于管道的有趣问题

背景是通过channel来传递数据。但是发现增加channel到一定量级的时候,程序输出和预期不一致。具体参见以下代码:

package main

import (
    "fmt"
    "time"
)

func changeFlow(left, right chan int) {
    left <- 1 + <-right
}

func main() {
    num := 100000 //调整num参数,观察不同结果
    left := make(chan int)
    right := make(chan int)
    lastChan := right

    startTime := time.Now()
    for i := 0; i < num; i++ {
        left, right = right, make(chan int)
        go changeFlow(left, right)
    }

    right <- 0
    result := <-lastChan

    fmt.Println("end at :", time.Now(), time.Since(startTime))
    fmt.Println(result)
}

通过go run main.go执行程序。
如上,当num<=100000的时候程序输出结果为the value of num。
一旦大于某个量级(可以调整到1,000,000)的时候,程序异常退出,如下图:

clipboard.png

小白求指教。

附上环境参数:
Go Version:go1.4.2 darwin/amd64
MacBook Pro (Retina, 13-inch, Early 2015)
2.7 GHz Intel Core i5
8 GB 1867 MHz DDR3

阅读 2.3k
1 个回答

我这里运行1000000没问题,运行10000000会直接死机。
你这个代码在运行到right<-0之前所有for生成的goroutine 都处于等待状态,num为多少就会生成多少个,1000000个大约时2G左右内存。
内存溢出了啊。
下面这样子,num多少都没问题。

package main

import (
    "fmt"
    "time"
)

func changeFlow(left, right chan int) {
    right <- 1 + <-left
}

func main() {
    num := 5000000 //调整num参数,观察不同结果
    left := make(chan int, 1)
    right := make(chan int, 1)

    startTime := time.Now()
    right <- 0
    for i := 0; i < num; i++ {
        left, right = right, make(chan int, 1)
        go changeFlow(left, right)
    }

    result := <-left

    fmt.Println("end at :", time.Now(), time.Since(startTime))
    fmt.Println(result)
}
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题