goroutine學習

還在學習中,理解的更爲透徹了再來總結。緩存

 

goroutine和channel

無緩存channel每一個發送和接收操做的同步性,由於因爲無緩衝區,因此其餘goroutine的發送會被阻塞在那邊,只有接收完畢後,某個goroutine才能寫入這個channel。異步

有緩衝區channel會使得讀寫routine(或者說是收發goroutine)是異步的,只要再緩衝區沒有滿,其餘的協程就能繼續寫,緩衝區不空,其餘的協程就能繼續讀。學習

 

unbuffered channel

若是是unbuffered channel,那麼發送者的goroutine會被阻塞,直到被別的goroutine接收後纔會繼續往下走。以下這段代碼是錯誤的,會一直被阻塞,go run的時候報錯:spa

1 func main() {
2     ch := make(chan int) //unbuffered channel
3     a := 10
4     ch <- a //blocked here
5     b := <-ch
6     fmt.Println(b)
7 }

fatal error: all goroutines are asleep - deadlock!code

goroutine 1 [chan send]協程

有兩種方法修改,第一種改爲buffered channel:blog

1 func main() {
2     ch := make(chan int, 1) //buffered channel
3     a := 10
4     ch <- a
5     b := <-ch
6     fmt.Println(b)
7 }  //正確輸出10

第二種是將發送這個動做放在一個goroutine中,這樣就不會阻塞主goroutine,主goroutine中的接收動做就得以完成:get

1 func main() {
2     ch := make(chan int) //unbuffered channel
3     a := 10
4     go func() { ch <- a }() // new a goroutine
5     b := <-ch
6     fmt.Println(b)
7 }

 ubuffered channel的發送和接收goroutine之間是同步的,不是異步的。帶緩衝區的channel是異步的。同步

 channel的零值是nil,注意:若是其通道是nil,它將永遠不會被選擇。it

判斷channel是否關閉

詳見:如何優雅的關閉channel

一、若是channel已經關閉,繼續往它發送數據會致使panic: send on closed channel 

二、關閉一個已經關閉的channel,會致使panic:close of closed channel 

三、讀取一個已經關閉的channel,能夠讀出沒有讀完的channel。讀完後會讀到零值。能夠屢次讀取。

 1 func test(){
 2     ch:=make(chan int,3)
 3     ch<-3
 4     ch<-2
 5     ch<-1
 6     close(ch)
 7     fmt.Print(<-ch)
 8     fmt.Print(<-ch)
 9     fmt.Print(<-ch)
10     fmt.Print(<-ch)
11     fmt.Print(<-ch)
12 }
13 //right

 不能經過判斷返回值是不是零值(包括nil)來判斷channel是否已經關閉,應爲nil能夠做爲值傳遞給channel:

1 func main() {
2     ch := make(chan interface{}, 10)
3     ch <- nil
4 
5     a := <-ch
6     fmt.Println(a)     //輸出nil,沒有close
7 }
相關文章
相關標籤/搜索