Golang协程执行结果不符预期,如何调整代码实现预期输出?
如何让Go协程按预期顺序执行
现有代码的问题分析
- 主goroutine启动
jobX协程后,会立刻执行jobY。Go的M:N调度器在没有阻塞操作的情况下,不会主动切换到新启动的协程,导致jobY会被完整执行完,才会轮到jobX运行。 wg.Wait()被放在fmt.Println("end")之后,导致"end"会在jobX执行完成前就被打印出来。
修改方案
- 在启动
jobX协程后,调用runtime.Gosched()主动让出CPU时间片,让调度器优先执行jobX协程。 - 将
wg.Wait()移到fmt.Println("end")之前,确保"end"在所有协程执行完毕后才打印。
修改后的完整代码
import ( "fmt" "runtime" "sync" "time" ) func jobX(wg *sync.WaitGroup) { defer wg.Done() for i := 0; i < 5; i++ { fmt.Println("routine X: ", i) if i == 2 { time.Sleep(3 * time.Second) } } } func jobY() { for i := 0; i < 5; i++ { fmt.Println("routine Y: ", i) } } func main() { var wg sync.WaitGroup fmt.Println("starting go routine...") wg.Add(1) go jobX(&wg) // 主动让出时间片,让jobX协程先执行 runtime.Gosched() jobY() // 等待jobX完成后再打印end wg.Wait() fmt.Println("end") }
执行流程说明
- 主goroutine启动
jobX后,调用runtime.Gosched()交出CPU,调度器切换到jobX执行,依次打印routine X: 0、routine X: 1、routine X: 2,随后进入3秒睡眠。 jobX睡眠时,主goroutine被调度继续执行,完整跑完jobY并打印所有routine Y的输出。jobY执行完毕后,主goroutine通过wg.Wait()等待jobX结束。jobX睡眠结束后,继续打印routine X: 3、routine X: 4,执行wg.Done()解除等待。- 最后主goroutine打印"end",完全符合预期输出。
内容的提问来源于stack exchange,提问作者Mirana
相关产品推荐
相关产品推荐

