這是一個建立於 的文章,其中的資訊可能已經有所發展或是發生改變。
channel會阻塞,阻塞的時候系統會繼續順序調用其他goroutine,main()也是一個goroutine,只是最先被執行。
看一個代碼:
package mainimport ( "fmt")func display(msg string, c chan bool) { fmt.Println(msg) c <- true fmt.Printf("end %s \n", msg)}func main() { c := make(chan bool) go display("hello", c) go display("hello1", c) go display("hello2", c) fmt.Println("start") <-c fmt.Println("end")}
這段代碼輸出結果:
starthelloend hellohello1hello2end
首先執行main函數,它是第一個goroutine,在main中又通過go語句建立了3個goroutine,但是不是立即執行的,它們必須等到main掛起後才會被調用。
當main執行到 <-c 的時候,根據channel特性,此時產生了阻塞,這時候系統會將main的goroutine掛起,繼續調用其他goroutine,也就是先前建立的3個goroutine,從第一個開始。
執行到:go display(“hello”, c)
這時候首先列印出hello,隨機函數中 c <- true 因為main已經在等待接受,所以這裡發送成功,繼續執行下面的代碼即列印出end hello,同時由於接受者main也接收到了資訊,main的goroutine阻塞取消,被啟用,可被繼續調用。
但這時候不會立即調用main的,因為雖然main被重新啟用了,但是它已經被排到剩下兩個goroutine後面了,所以接下來實際上繼續執行的goroutine是 go display(“hello1”, c) 。
在 go display(“hello1”, c) 中,hello1首先被列印出來,隨機 c <- true 像channel中發送訊息,但是由於沒有接收者(main已經接收過了),所以這個goroutine也被阻塞,系統繼續調用下一個goroutine,同理只輸出hello2,最後再調用main的goroutine,列印出end。
以上是無緩衝的channel,有緩衝的阻塞原理與這個不一樣。