在使用多个 goroutine 打印内容时,channel使用的不恰当而导致主线程未等待其它 goroutine 全部执行完毕而退出,造成打印内容不全的问题
package main import ( "fmt" "runtime" ) // 从 1 至 1 亿循环叠加,并打印结果。 func print(c chan bool, n int) { x := 0 for i := 1; i <= 100000000; i++ { x += i } fmt.Println(n, x) if n == 9 { // 当程序运行到第10个goroutine时,给channel添加值,解除阻塞 c <- true } } func main() { // 使用多核运行程序 ,不使用多核时可以正常打印,runtime.NumCPU() 获取cpu个数 runtime.GOMAXPROCS(runtime.NumCPU()) //使用时,不能打印所有chan,显示结果不是顺序的 c := make(chan bool) for i := 0; i < 10; i++ { go print(c, i) } <-c // 取channel值,无值时,程序阻塞 fmt.Println("DONE.") }
解决方案一:利用 chan 的缓存机制
package main import ( "fmt" "runtime" ) // 从 1 至 1 亿循环叠加,并打印结果。 func print(c chan bool, n int) { x := 0 for i := 1; i <= 100000000; i++ { x += i } fmt.Println(n, x) c <- true } func main() { // 使用多核运行程序 runtime.GOMAXPROCS(runtime.NumCPU()) c := make(chan bool, 10) // 有缓冲的channel for i := 0; i < 10; i++ { go print(c, i) } for i := 0; i < 10; i++ { <-c } fmt.Println("DONE.") }
解决方案二:使用 sync 包的 WaitGroup
package main import ( "fmt" "runtime" "sync" ) // 从 1 至 1 亿循环叠加,并打印结果。 func print(wg *sync.WaitGroup, n int) { x := 0 for i := 1; i <= 100000000; i++ { x += i } fmt.Println(n, x) // 标识一次任务完成 wg.Done() } func main() { // 使用多核运行程序 runtime.GOMAXPROCS(runtime.NumCPU()) // 创建等待组 wg := sync.WaitGroup{} // 设置需要等待的对象个数 wg.Add(10) for i := 0; i < 10; i++ { go print(&wg, i) } // 等待所有任务完成 wg.Wait() fmt.Println("DONE.") }
浙公网安备 33010602011771号