无论是java还是go,开启线程和协程的时候,执行的顺序都是一样的。
例子1:
func funcB() {
println("funcB")
}
func funcA() {
println("funcA")
}
func main() {
funcA()
go funcB()
select {}
}
实际的执行顺序还是顺序执行完FuncA(),再Go FuncB().输出为
funcA
funcB
例子2:
func funcB() {
println("funcB")
}
func funcA() {
println("funcA")
}
func main() {
go funcB()
funcA()
select {}
}
实际的执行顺序是开启FuncB()协程,然后继续往下执行funcA()为什么输出还是funcA和funcB
funcA
funcB
因为当开启协程的那一刹那(还没执行打印B),主协程和funcB的协程就开启了资源竞争,所以在下一个执行分片,可能已经是执行funcA()里的打印A了,然后select{}阻塞,funcB协程获得执行分片,打印funcB。
例子3:
打印1000个funcD的时候,在打印某一个funcD的时候就开始调度输出执行go funcB2的内容了。
例子4:
这个例子表明,在没有go之前的语句,都是顺序执行的(打印100次A),不会调度go的子协程。因为那时候还没开启子协程。
开启子协程后,什么时候能获得优先权去运行是不固定的,根据系统调度来决定的。
子协程要获得调度执行,有三种情况:
- 主协程还没执行完毕的时候,与主协程竞争
- 主协程所有内容已经执行完毕
- 主协程主动阻塞。比如chan的操作或者主动Sleep