goroutine调度器简介
G-P-M模型,下面这张图很直观。
具体内容,参考以下链接,已经说得很详细,不再重复。
例子
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
   | package main import "fmt" import "time" import "runtime"
  func main() {     var x int     fmt.Println("GOMAXPROCS =", runtime.GOMAXPROCS(0) )     threads := runtime.GOMAXPROCS(0)     for i := 0; i < threads; i++ {         go func() {             for { x++ }         }()     }     fmt.Println("Before time.Sleep")     time.Sleep(time.Second)     fmt.Println("After time.Sleep")     fmt.Println("x =", x)   }
   | 
 
运行之后,发现main函数运行到Sleep之后,就卡住了,是什么原因呢?
1 2 3 4 5
   | [patrickxu@vm1 src]$ ./test GOMAXPROCS = 8 Before time.Sleep
 
 
   | 
 
因为main函数在执行time.Sleep(time.Second)后,main函数本身占据的P(G-P-M模型中的P)也被for{ x++ }一直占着,抢占的机制。这下总共8个P,全部一直被for { x++ }占着,永远轮不到主函数了。
runtime.GOMAXPROCS(0)默认等于CPU核数8。每个P可以分配到一个M(即线程),总共2 + runtime.GOMAXPROCS(0) = 10个。
1 2 3 4 5 6 7 8 9 10 11
   | [patrickxu@vm1 ~]$ ps -eLf | grep test 519      26778 26325 26778  0   10 00:18 pts/42   00:00:00 ./test 519      26778 26325 26779  0   10 00:18 pts/42   00:00:00 ./test 519      26778 26325 26780 99   10 00:18 pts/42   00:02:28 ./test 519      26778 26325 26781 99   10 00:18 pts/42   00:02:28 ./test 519      26778 26325 26782 99   10 00:18 pts/42   00:02:28 ./test 519      26778 26325 26783 99   10 00:18 pts/42   00:02:28 ./test 519      26778 26325 26784 99   10 00:18 pts/42   00:02:28 ./test 519      26778 26325 26785 99   10 00:18 pts/42   00:02:27 ./test 519      26778 26325 26786 99   10 00:18 pts/42   00:02:28 ./test 519      26778 26325 26787 99   10 00:18 pts/42   00:02:28 ./test
   | 
 
如果把time.Sleep(time.Second)去掉后,马上全部执行结束。
1 2 3
   | [patrickxu@vm1 src]$ ./test GOMAXPROCS = 8 x = 0
   | 
 
当然也可以把GOMAXPROCS设打,比如threads := runtime.GOMAXPROCS(10)。有足够多的P,也可以运行完。