golang裡channel的實現原理
來源:互聯網
上載者:User
這是一個建立於 的文章,其中的資訊可能已經有所發展或是發生改變。channel是訊息傳遞的機制,用於多線程環境下lock free synchronization.它同時具備2個特性:1. 訊息傳遞2. 同步
golang裡的channel的效能,可以參考前一篇:http://blog.sina.com.cn/s/blog_630c58cb01016xur.html此外,內建的runtime package裡已經提供了benchmark代碼,可以運行下面的命令查看其效能:go test -v -test.bench=".*" runtime
在我的pc上的結果是:BenchmarkChanUncontended 50000000 67.3 ns/opBenchmarkChanContended 50000000 67.7 ns/opBenchmarkChanSync 10000000 181 ns/opBenchmarkChanProdCons0 10000000 198 ns/opBenchmarkChanProdCons10 20000000 98.2 ns/opBenchmarkChanProdCons100 50000000 73.4 ns/opBenchmarkChanProdConsWork0 1000000 1874 ns/opBenchmarkChanProdConsWork10 1000000 1805 ns/opBenchmarkChanProdConsWork100 1000000 1771 ns/opBenchmarkChanCreation 10000000 195 ns/opBenchmarkChanSem 50000000 66.3 ns/op
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的實現 }