go學習筆記_Routine和Channel上

go語言併發編程上

傍晚抽空學習了下go語言的併發編程,從goroutinechannel機制,從開始的稀裏糊塗到現在撥開雲霧見太陽的感覺,學習的過程總是令人亢奮的!當然目前的理解還是不夠透徹的。下篇將舉例來分析下。

goroutine

類似開闢進程、線程做法,go語言所採用的爲 goroutine 。用法極其簡單,也就是使用go關鍵字,使用方法有兩種:

  • 定義一個函數functionName,要異步調用時使用語句go functionName即可。

  • 使用匿名函數,用法爲go func(參數列表){函數執行體}(),說明最後一個()作用就是讓該函數執行。

下面簡單代碼加深下:

    /////////第一種示例代碼:///////////
    func sayHello(name string){
        fmt.Println("hello"+name)
    }
    //主程序入口
    func main(){
        go sayHello("PMST")
    }
    /////////第二種示例代碼://////////
    //主程序入口
    func main(){
        go func(){
            fmt.Println("hello world")
        }()     //別忘記這裏的()
    }

現在來講下go關鍵字作用,一旦將go放在函數之前,意味分配一個子routine讓這個函數自個玩去(有點自身自滅的感覺),而主routine則繼續該幹嘛幹嘛。打個比方,手頭有一堆數據,需要經過超級複雜,超級耗時的計算才能得出答案。顯然我們的主routine不可能只幹這一件事,它還有其他事情需要處理。因此,我們開闢一個routine讓其自個算去。

那麼問題來了,這麼做確實解決了主routine不被鎖死的問題,又能夠完成了耗時計算,可是計算出答案之後,如何回傳給主routine使用呢?

這也就是下面channel的使用了

channel

goroutine 之間如何進行數據的通信?如下兩種:

  1. 共用內存內存空間。

  2. Go語言推薦的通信機制channel

接下來是我對channel的一些理解:

  • Goroutine使用channel 接收或者發送值,而這些值只能是特定的類型,由自己指定,比如兩個routine之間相互傳值爲int類型,那麼channel類型就是chan int

  • 通過make來創建channel,例如無緩存ci := make(chan int),指定緩存cib := make(chan int,2)。很明顯可以看出,區別在於後面的表述,後者表示給這個通道分類了2個緩存空間,至於區別,下文馬上給出。

  • channel 通過<- 來接收和發送數據。例如 channel <- value ,顯然就是把值 value 發送到通道 channel 中; value := <- ch ,注意箭頭,表示從通道 channel 讀取數據給 value ,或者可以說從通道channel接收數據賦值給value。順便提及其他的寫法<- channel,顯然也是從通道讀取數據,但是沒有賦值給任何一個變量,因此表示丟棄!

關於channel的阻塞問題,我想有必要着重梳理下。請看下面的總結

首先通道的接收和發送都是阻塞的,除非與之對應的一端已經準備好。通過舉例來說明是最好不過了。

  1. 新建一個通道,channel_c := make(chan int),注意是沒有分配緩存的。

  2. 隨後往通道寫入數據,channel_c <- value,由於沒有分配緩存,因此這裏會被堵塞掉,換句話說就是卡死在這裏,只能等待,等待程序某個地方從該通道讀取數據!(ps:就好比非常短的管子,就往裏塞了一個數據,就要漏出來,因此我一直手”扶着”數據,騰不出手幹下面的事了。只有當接收方來拿數據了才能騰出手來幹別的事。)

  3. 2015.04.22 -> 對上面比喻修改。ps:上面比喻的不是很恰當,我想是不是可以這麼認爲,channel是連通兩個routine的通道,當發送者向channel裏發送數據,卻遲遲等不到接收者,但秉着盡職盡責的思想,始終等待在那個位置,即channel_c <- value這條發送語句處,直到接收者接收了通道數據,纔可以進行下一條語句。那麼假如有緩存就不同了,就好比一個驛站,拿着數據到通道這發送“郵件”,儘管可能沒有接收者,但是我卻可以先暫時放到“驛站”(緩存)這裏,然後繼續幹自己的活,等下次再向通道發送數據時發現緩存滿了,就只能耐心等待,除非這時有人來取數據,騰出緩存空間了,纔可以寫入數據。

  4. 現在換成從通道讀取數據,v := <- channel_c,分兩種情況:當channel_c通道中有數據時,那肯定不會堵塞,很順利的讀過來;當channel_c通道沒有數據時,那麼自然又堵死了,除非程序其它地方往通道寫入數據了!

  5. 最後講講關於分配了緩存的通道,例如:channel := make(chan int,2)。假如這時候往通道寫入數據channel <- 2,由於分配了緩存,意味着是我可以直接寫入,不會堵塞了,但這僅當我的緩存區未滿的情況下纔不會堵塞。下面往通道寫入一個channel <- 3,這是沒有問題的。不過緩存已經填滿了!假如這時候你再寫的話就會堵塞,只有程序某個地方從改通道讀取數據騰出地方了,你纔可以寫入!

發佈了75 篇原創文章 · 獲贊 70 · 訪問量 10萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章