前文“深入淺出Golang關鍵字"go"”最后留了幾個問題:
func main() {
runtime.GOMAXPROCS(1)
for i := 0; i < 10; i++ {
go println(i)
}
runtime.Gosched()
time.Sleep(time.Second)
}
runtime.Gosched()
這一行代碼。
如果注釋掉結果會怎樣踏枣??
如果把這一行換成 runtime.Goexit() 或者 os.Exit(0) 又會是如何呢勘天?恍涂?
如果有關注到這個問題并且自己嘗試過的朋友會發(fā)現(xiàn):
- 如果把 runtime.Gosched() 注釋掉,結果會是 0~9妇拯;
- 如果換成 runtime.Goexit(),結果會是先輸出 0~9洗鸵,然后程序 panic;
- 如果是 os.Exit(0)越锈,則什么也不會輸出。
對于 0~9 的結果膘滨,很多人會奇怪甘凭,runtime.Gosched() 到底怎樣影響到結果的?而 runtime.Goexit() 與 runtime.Gosched() 之間又存在怎樣的區(qū)別呢火邓?
runtime.Gosched() 主要做了一件事就是嘗試交出 P 操作權限对蒲,等待其它 gorotine 執(zhí)行完成后再繼續(xù)執(zhí)行當前 gorotine,結合前文的 next 位置贡翘,則輸出了 9 0~8 這樣的結果蹈矮。
但是當把這一行注釋了,程序會卡在 time.Sleep 處鸣驱,這時候 go 程序設計中的另一個東西出場了——sys monitor 線程泛鸟,這是 go 語言設計中的唯一一個(主線程除外)獨立的線程。它的作用是監(jiān)控 gorotine 狀態(tài)的踊东。當主 goroutine 在 sleep 時北滥,monitor 認為占用時間不符合預期,它會把 P 讓出來闸翅,而自己則進入 P 的 gorotine 隊列等待再芋。那么問題來了,P 有 next 位置呀坚冀,所以這時候 main gorotine 就占了 next 位置济赎。從而導致輸出順序變成 0~9了。
Goexit() 與 Gosched() 唯一不同的地方則是它會丟棄此行代碼后的所有堆棧,
并且如果丟棄的是 main gorotine 的話會 panic司训。結果也自然是輸出 0~9 然后 panic 了构捡。
os.Exit() 自不必多說了。