先来看一段代码
package main
import (
"fmt"
"time"
)
var sem = make(chan int, 1)
type Request struct {
Name string
}
func Serve(queue chan *Request) {
for req := range queue {
sem <- 1
go func() {
fmt.Println("groutine receive: ", req)
<-sem
}()
// runtime.Gosched() // 这里打不打开注释有什么作用呢?
}
}
func main() {
queue := make(chan *Request, 4)
queue <- &Request{"1"}
queue <- &Request{"2"}
queue <- &Request{"3"}
queue <- &Request{"4"}
close(queue)
Serve(queue)
time.Sleep(1 * time.Second)
}
直接运行这段代码的输出为
groutine receive: &{2}
groutine receive: &{3}
groutine receive: &{4}
groutine receive: &{4}
而如果将 runtime.Gosched()注释打开的话输出结果为
groutine receive: &{1}
groutine receive: &{2}
groutine receive: &{3}
groutine receive: &{4}
为什么会有结果不同呢,这是因为 goroutine 需要cpu时间片去执行。而 runtime.Gosched() 可以让出cpu时间片。
这里不得不说 Goroutine 在执行的时候是有陷阱的,如何保证我们的 goroutine 都会执行呢?
在工作代码比较多的时候,我们遇到上述错误的机会很少。因为我们的程序基本都会执行runtime中提供的一些功能,例如channel,系统调用, fmt.Sprint, Mutex, time.Sleep等,这些使用会使调试器让出时间片,从而让其它有 goroutine 有机会执行。