协程属于用户态线程,逻辑由用户代码控制。

系统本身不对 goroutine 数目进行限制。

虽然 golang 中协程开销很低,但是在一些情况下还是有必要限制一下协程的开启数,如果你的协程数太过庞大,可能出现:

  • 系统资源占用率不断上涨
  • 输出一定数量后:控制台就不再刷新输出最新的值了
  • 信号量:signal: killed

解决方式: buffered channel + sync.WaitGroup()

自己改的一个小 demo:

package main

import (
    "fmt"
    "math"
    "runtime"
    "strconv"
    "sync"
    "sync/atomic"
)
var wg sync.WaitGroup
var count int32

const goNums  = math.MaxInt32

// 模拟下载页面的方法
func download(url string) {
    defer wg.Done()
    atomic.AddInt32(&count,1)
    fmt.Println("download from ", url)
}

func main() {

    runtime.GOMAXPROCS(8)
    urls := [goNums]string{}
    for i := 0; i < goNums; i++ {
        urls[i] = "url" + strconv.Itoa(i)
    }
    wg.Add(goNums)
    for i := 0; i < len(urls); i++ {
        go download(urls[i])
    }

    wg.Wait()
    fmt.Println(count)
}

参考

  1. golang 限制协程的最大开启数
  2. 来,控制一下 goroutine 的并发数量