1.读写操作的重新排序
Go 可能会重排一些操作的执行顺序,可以保证在一个 goroutine 中操作是顺序执行的,但不保证多 goroutine 的执行顺序:
var _ = runtime.GOMAXPROCS(3)
var a, b int
func u1() {
a = 1
b = 2
}
func u2() {
a = 3
b = 4
}
func p() {
println(a)
println(b)
}
func main() {
go u1() // 多个 goroutine 的执行顺序不定
go u2()
go p()
time.Sleep(1 * time.Second)
}
运行效果:
如果你想保持多 goroutine 像代码中的那样顺序执行,可以使用 channel 或 sync 包中的锁机制等。
2.优先调度
你的程序可能出现一个 goroutine 在运行时阻止了其他 goroutine 的运行,比如程序中有一个不让调度器运行的 for 循环:
func main() {
done := false
go func() {
done = true
}()
for !done {
}
println("done !")
}
for 的循环体不必为空,但如果代码不会触发调度器执行,将出现问题。
调度器会在 GC、Go 声明、阻塞 channel、阻塞系统调用和锁操作后再执行,也会在非内联函数调用时执行:
func main() {
done := false
go func() {
done = true
}()
for !done {
println("not done !") // 并不内联执行
}
println("done !")
}
可以添加 -m 参数来分析 for 代码块中调用的内联函数:
你也可以使用 runtime 包中的 Gosched() 来 手动启动调度器:
func main() {
done := false
go func() {
done = true
}()
for !done {
runtime.Gosched()
}
println("done !")
}
最后编辑: kuteng 文档更新时间: 2024-04-01 11:02 作者:kuteng