golang channel本質——共享內存


channel是golang中很重要的概念,配合goroutine是golang能夠方便實現並發編程的關鍵。channel其實就是傳統語言的阻塞消息隊列,可以用來做不同goroutine之間的消息傳遞,由於goroutine是輕量級的線程能夠在語言層面調度,所以channel在golang中也常被用來同步goroutine。

一般channel的聲明形式為:var chanName chan ElementType 
ElementType指定這個channel所能傳遞的元素類型。

定義一個channel也很簡單,直接使用內置的函數make()即可: 
ch := make(chan int,bufferSize) //bufferSize為緩沖區的大小,可以不傳遞該值代表不帶緩沖區的channel

消息傳遞

帶有緩沖區的channel一般用來做不同goroutine之間的消息傳遞。最經典的解釋莫過於生產者-消費者了。生產者向channel中寫數據,如果channel緩沖區已滿,則生產者會被阻塞直到消費者消費緩沖區中的數據后才能被喚醒。 
消費者從channel中讀取數據,如果緩沖區中沒有任何數據則消費者會阻塞直到生產者將數據寫入才能被喚醒。

假設我們有30個學生做作業,做完作業后由一個老師批改作業。用go怎么實現呢,我們首先定義一個帶有緩沖區HomeWork chan(緩沖區的大小與學生數目相同,主要是為了防止學生提交作業時阻塞),學生做完作業向hwChan中發送數據,老師等待hwChan中有數據就取出學生作業然后批改。

channel是消息傳遞的機制,用於多線程環境下lock free synchronization.

它同時具備2個特性:
1. 消息傳遞
2. 同步
 
channel的實現,都在$GOROOT/src/pkg/runtime/chan.c里
 
它是通過共享內存實現的
struct Hchan {
}
 
ch := make(chan interface{}, 5)

具體的實現是chan.c里的 Hchan
* runtime·makechan_c(ChanType *t, int64 hint)
此時,hint
=5, t=interface{} 它完成的任務就是: 分配hint * sizeof(t) + sizeof(Hchan)的內存空間[也就是說,buffered chan的buffer越大,占用內存越大] ch <- 5 就會調用 void runtime·chansend(ChanType *t, Hchan *chan, byte *ep, bool *pres) lock(chan) 如果chan是buffer chan { 比較當前已經放入buffer里的數據是否滿了A 如果沒有滿 { 把ep(要放入到chan里的數據)拷貝到chan的內存區域 (此區域是sender/recver共享的) 找到receiver goroutine, make it ready, and schedule it to recv } else { 已經滿了 把當前goroutine狀態設置為Gwaiting yield } } else { // 這是blocked chan 找到receiver goroutine (channel的隱喻就是一定存在多個goroutine) 讓該goroutine變成ready (之前是Gwaiting), 從而參與schedule,獲得控制權 具體執行什么,要看chanrecv的實現 }

 

參考:http://www.voidcn.com/blog/kjfcpua/article/p-2921075.html
http://shanks.leanote.com/post/%E6%B7%B1%E5%BA%A6%E5%89%96%E6%9E%90channel

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM