go語言併發編程下
上文從基礎層面講解了goroutine 和 channel ,關於如何使用都停留下嘴皮子上,因此下篇選用幾個最簡單的例子來鞏固下。另外推薦下自己的個人博客,你可以先點進行看下內容是否對您有幫助,在選擇收藏或者直接x掉。
個人博客地址:Colourful Code
正文
首先,上文說到channel 有兩種情況:
未分配緩存
分配一定緩存
例子從這兩點入手給出。
未分配緩存
package main
import "fmt"
//求和函數sum
func sum(a []int,c chan int){
sum :=0
for _,v := range a{
sum += v
}
c<-sum //向通道c 寫入數據值 sum
}
//主程序入口
func main(){
a:= []int{1,3,5,2,-2}
c:= make(chan int)
go sum(a[:],c) //開闢一個goroutine 用於進行sum函數執行
x:= <-c //讀取c通道的值賦值給x
fmt.Println(x)
}
從主程序開始分析,如下分爲幾個步驟:
聲明定義了一個數組 a
聲明定義了一個通道 c,注意是沒有給定緩存的。
正因爲加了go關鍵字 ,所以爲sum函數開闢一個goroutine,同時給函數傳入參數:數組a和通道c。這個時候程序除了主routine,也就是main函數。與此同時還有爲sum開闢的子routine,這個子routine所要做的就是對傳入的數組進行求和,並且將結果值寫入通道c中。
主routine執行完
go sum(a[:],c)
這條語句之後,馬上就可以執行下一條語句了。也就是x:=<-c
。 這裏就有點意思了。要根據實際情況分2種情況來說:c 通道有值和無值。- c 通道有值,這意味着子goroutine 中進行的求和運算先完成,通過語句
c<-sum
將結果值寫入通道時,由於完成的太早,沒有接收方從通道讀取數據造成了堵塞,子routine中的程序卡死在這裏,等待接收者讀取數據。直到主routine執行了x:=<-c
這條語句,順利的從通道讀取到了數據,於此同時子routine中c<-sum
由於通道數據被讀走,這裏不再堵塞,子routine中的sum函數執行完畢。 - c 通道沒有值,意味着子goroutine 中進行的求和運算還未完成(假如這裏的求和運算改爲大數據處理,我想要花費很多時間。),數據還未寫入到c通道中,因此由於通道內沒有數據,主routine中會堵塞在
x:=<-c
這條語句上,等待子routine完成數據計算,執行c<-sum
語句往通道中寫數據。這時候主routine中 順利讀取通道c中的值,賦值給x,打印出來。
- c 通道有值,這意味着子goroutine 中進行的求和運算先完成,通過語句
分配緩存
package main
import "fmt"
func main(){
c:=make(chan int,2)
c <- 10
c <- 20
fmt.Println(<-c)
fmt.Println(<-c)
}
由於理解了channel 工作機制,那麼分配緩存理解起來容易一些。
首先聲明定義一個緩存大小爲2的特定類型爲int的通道c
往通道寫入值10,想一想,倘若沒有分配緩存,那麼程序會堵塞在這裏,除非其他routine會從該通道讀取數據,但這顯然不可能,因爲這時候是在主routine中,你又沒有創建子routine,所以最後只會報錯,“all goroutines are asleep - deadlock!”
這時候你應該已經理解了,正因爲分配了緩存,因此能夠順利的寫入值10,接下來往通道寫入值20,顯然由於緩存還有空間,寫入沒有問題,不會造成堵塞,程序繼續執行下去!
<-c
就是從通道中讀取數據,會打印10打印20,有種FIFO(注:“first in first out”,先入先出)的感覺,由於我們往通道緩存中寫入值10,再寫入值20,取出時就應該有順序的先取出值10,再取出值20。
結尾:
博主是一個剛入坑的go小菜鳥,對go語言理解可能還不是很透徹,倘若哪裏理解不對,或者寫的有問題,歡迎指正,踩踩更健康嘛,不過希望您能留言告訴我爲啥踩的理由嗎,好讓我改正,這也算一種學習不是嗎?最後謝謝!