學習go語言差不多也有一周了,筆記也記了不少了。但是對於go這種新語言,並沒有從功能方面去了解過。畢竟,要是從思想上來認識它,對我來說還是有難度的。所以我對go的理解現在還是在一些比較基礎的層次,都是對比其與我熟悉的其他語言的異同。鋪墊了這么多,就是想說,我的理解可能是片面的,甚至是錯的,希望各位大牛指點啊!
在某處剽竊了關於go語言的說明:是一個在語言層面實現了並發機制的類C通用型編程語言。而在並發實現中,主要是用channel來實現通信的。其中channel包括兩種,緩沖的channel和非緩沖的channel。(由於個人組織語言的能力有限,也怕說錯,后面一句也是剽竊別人的)緩沖的channel:保證往緩沖中存數據先於對應的取數據,簡單說就是在取的時候里面肯定有數據,否則就因取不到而阻塞。而非緩沖的channel:保證取數據先於存數據,就是保證存的時候肯定有其他的goroutine在取,否則就因放不進去而阻塞。單單看這個字面意思,其實還是不知所以然,那就。。。。。。上例子。其實好多時候,真的是懶得去解釋什么,也不太喜歡跟別人討論到底該是什么結果,直接試試比說多少都更有意義啊。可是,偏偏有那么一小撮人,非要整個面紅耳赤,還不屑於我說的試試,說“我要是想試還用問你啊?”。碰到這樣的人,算我倒霉。從開始學編程,老師就告訴我們,拿到問題先分析,到底結果怎樣,動手實踐下,再分析原因。好吧,我好像又扯遠了。言歸正傳,談channel。
1 package main 2 import( 3 "fmt" 4 ) 5 6 var a string 7 var c = make(chan int,3)//此處定義為緩沖的channel 8 func ff(){ 9 a ="hello world" 10 ca := <-c 11 fmt.Println(ca) 12 } 13 14 func main(){ 15 go ff() //開啟一個goroutine 16 c<-3 17 fmt.Println(a) 18 19 }
可以先試想下運行結果。其結果就是,沒有任何輸出,程序直接就結束了。我的理解:因為這是個緩沖的channel(var c = make(chan int,3)),所以存的優先級會高,如果存入緩沖的不足三個,那就等下去(名詞叫阻塞),等到程序都結束了。這里要好好理解阻塞的含義。剛開始我以為阻塞只是阻止了channel變量的讀取,后來試了幾次才知道,所謂的阻塞,說白了就是什么都不干了,就等着某個條件滿足之后才會有事件的執行。
然后改變參數或者是做一些比較小的改動,看程序的運行結果是否會發生變化。在16行后面再增加兩個存值操作,c<-11 ;c<-12數值是多少無所謂,因為就只有一次取,取到的肯定是存進去的第一個值。可以猜一下這次的運行結果。這次,跟原來一樣,還是沒有輸出,因為三次存操作之后,阻塞就解開了,開始執行取操作,但是取完之后緩沖中又不足三個了,沒辦法,還得阻塞,一直等到了程序結束,hello world被漫長的等待覆蓋了。再增加一個存操作,就得到了結果,3 helloworld。過程大致為,當三個存滿了之后,阻塞被解除了,去執行一個goroutine,即進行了一次取操作,輸出3,取完之后又被阻塞,然后又存了一個,阻塞解除,執行后面的操作,輸出了hello world.
但是在上述能輸出結果的基礎上,在增加一個村操作,又會怎樣呢?別急,試下就知道了。結果就是報錯了,
死鎖了,能不死鎖嗎,緩沖滿了,還要繼續往里面填,但是又沒有其他的goroutine去取,只能死鎖。這樣的測試還可以去做很多,我也確實做了不少,然后總結出規律來。只有在緩沖滿了,沒有goroutine去取,卻還存或者是緩沖空了,沒有存的操作,卻還在取都會報上面的死鎖信息。如果是等待,那就只是等待了,主函數會直接結束,不報什么信息。
關於無緩沖的,我還沒有研究太清楚,待續
大致過程就是如此,對於channel,要想清楚了,要不然去理解以后更難得程序就要麻煩了。