go 協程與主執行緒強佔執行
阿新 • • 發佈:2019-02-11
最近在學習了go 語言 , 正好學習到了 協程這一塊 ,遇到了困惑的地方.這個是go語言官方文件 . 在我的理解當中是,協程只能在主執行緒釋放時間片後才會經過系統排程來執行協程,其實正確的也確實是這樣的,但是我遇到了協程強佔主執行緒的一個問題,經過幫助,現在已經瞭解.廢話不多說,先看程式碼
1 package main 2 3 import ( 4 "fmt" 5 "time" 6 ) 7 8 func main() { 9 go say("world") 10 say("hello") 11 /* 12 fmt.Println("---------------1")13 14 a := []int{7, 2, 8, -9, 4, 0} 15 fmt.Println("===", a[:len(a)/2]) 16 c := make(chan int) 17 go sum(a[:len(a)/2], c) 18 go sum(a[len(a)/2:], c) 19 x, y := <-c, <-c // receive from c 20 21 fmt.Println(x, y, x+y) 22 23 fmt.Println("---------------2")24 25 c2 := make(chan int, 2) 26 c2 <- 1 27 c2 <- 2 28 fmt.Println(<-c2) 29 fmt.Println(<-c2) 30 31 fmt.Println("---------------3") 32 c3 := make(chan int, 10) 33 go fibonacci(cap(c3), c3) 34 for i := range c3 { 35 fmt.Println(i)36 } 37 38 fmt.Println("---------------4") 39 c4 := make(chan int) 40 quit := make(chan int) 41 go func() { 42 for i := 0; i < 10; i++ { 43 fmt.Println(<-c4) 44 } 45 quit <- 0 46 }() 47 fibonacci2(c4, quit) 48 49 fmt.Println("---------------5") 50 tick := time.Tick(100 * time.Millisecond) 51 boom := time.After(500 * time.Millisecond) 52 for { 53 select { 54 case <-tick: 55 fmt.Println("tick. ") 56 case <-boom: 57 fmt.Println("BOOM!") 58 return 59 default: 60 fmt.Println(" .") 61 time.Sleep(50 * time.Millisecond) 62 } 63 }*/ 64 } 65 66 func say(s string) { 67 for i := 0; i < 5; i++ { 68 time.Sleep(100 * time.Millisecond) 69 fmt.Println(s) 70 } 71 }
先看兩次程式碼執行結果
第一次: (結合上面程式碼檢視列印順序)
第二次:(結合第一次檢視列印順序)
是不是發現了每次的列印順序是不同的
這個就是協程強佔執行
我們先來看下它的執行循序 , 主執行緒執行====>釋放時間片====>協程執行==>釋放時間片====>主執行緒執行
根據這段程式碼
1 say("hello")
我們知道,這個是屬於主執行緒裡面的,所以優先執行(注意實參是"hello")
然後看看 say 方法
1 func say(s string) { 2 for i := 0; i < 5; i++ { 3 time.Sleep(100 * time.Millisecond) 4 fmt.Println(s) 5 } 6 }
當執行到迴圈裡面的
time.Sleep(100 * time.Millisecond)
會釋放時間片,同時 暫停執行程式碼,系統排程到協程
go say("world")
也是同一個方法,同時也會執行
time.Sleep(100 * time.Millisecond)
釋放時間片
於是再列印的時候就會出現強佔執行