Skip to content

xd1lab/go-analysis-goroutine

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

6 Commits
 
 
 
 

Repository files navigation

原始問題出處:
https://stackoverflow.com/questions/35153010/goroutines-always-execute-last-in-first-out
https://studygolang.com/topics/9608


問題範例code:

func c(i int){
  fmt.Println(i)
}


func main() {
   runtime.GOMAXPROCS(1)

   for i:=0; i< 11; i++ {
       go c(i) // print依序為10 0 1 2 3 4 5 6 7 8 9
   }

  fmt.Scanln()
}

為什麼是10先被打印出來?

首先要先知道goroutine隊列執行本身就可能是無序的,其原理可去理解Golang的GMP模型
單核心在數字大時就不會總是最後一個被優先print出來、也不會總是照順序
接著我們用trace tool做三個實驗,看看單核心在什麼情況下最後一個數字不會被先print


* 實驗一:for 0~999 單核心

結果:執行後第一個被print的為999
螢幕快照 2019-07-18 下午5.02.58.png

1.先看trace總覽,goroutines在runtime.main執行結束後才開始調用(此圖青藍色最高峰處),也就是1000個G開始被單核心執行

螢幕快照 2019-07-18 下午4.49.47.png

2.接著看看第一個被調用的G,就是print數字999的goroutine,可以看到Start Stack Trace有成功執行syscall.write,將999打印到螢幕上 螢幕快照 2019-07-18 下午4.39.00.png


* 實驗二:for 0~9999 單核心

結果:執行後第一個不為9999
螢幕快照 2019-07-18 下午5.14.26.png

1.與實驗一相同,goroutines在runtime.main執行結束後才開始下降,但可以注意到GC出現了! 螢幕快照 2019-07-18 下午5.11.09.png

2.來到第一個被調用的G,可以發現應該就是要執行print數字9999的goroutine,卻沒有執行syscall.write,而是進入GC的程序
螢幕快照 2019-07-18 下午4.38.34.png


* 實驗三:for 0~999 多核心

結果:執行後亂序出現
螢幕快照 2019-07-18 下午5.20.41.png

1.從trace可以發現goroutines不會再等待 runtime.main執行完畢才開始被調用
螢幕快照 2019-07-18 下午5.22.00.png


* 實驗總結:

我們可以發現在單核心情況下,runtime.main的過程中G不斷在被創建,然而要等到runtime.main結束才開始消耗G。

  • 問題一: 為什麼第一個被調用的G是for迴圈中最後一個999呢?
    解釋
    stackoverflow也有類似問題被問過(註一),但回答依舊是goroutine本身隊列無序,因此我們只能大略推論其調度器邏輯是為了效率,也就是最後一個goroutine被創建後就直接消耗掉,因此才會出現第一個被執行的G—是for迴圈中最後一個被創建的G。
  • 問題二:同樣是單核心情況,為什麼迴圈數字變大,第一個print的不是最後一個數字呢?
    解釋
    從實驗二可以發現是GC從中作梗,第一個被調用的G仍然是最後被創建的G,但是因為GC的作用下syscall.write被延後執行。
  • 問題三:單核心跟多核心有什麼差異?
    解釋
    實驗三可以簡潔明瞭發現問題在runtime.main創建G時,其他CPU可以同時執行G,就不會有最後創建的G第一個被消耗情況。

註一:https://stackoverflow.com/questions/35153010/goroutines-always-execute-last-in-first-out

後記:
若喜歡請幫忙給個星星start,有任何觀念錯誤也請多多指教~
https://github.com/jou66jou/go-analysis-goroutine

trace tool 教學:
https://www.itcodemonkey.com/article/5419.html

Golang的GMP模型介紹:
https://www.cnblogs.com/sunsky303/p/9705727.html

Releases

No releases published

Packages

 
 
 

Languages