1. 程式人生 > >golang的協程和通道的分析

golang的協程和通道的分析

每個協程對應於每個併發的事件,程式可以不用協程,這樣執行的效率不如用協程的要快。

同時執行的協程數,與cpu數進行匹配最合適,否則會出現deadlock。

協程間的通訊,通過chan來實現,而多個chan可以組成管道,來順序的傳遞資料。

<-在chan的左側是用於輸出,<-在chan的右側是用於輸入,在函式呼叫時可以通過<-來設定chan的讀寫許可權。

寫個demo如下:

package main
import (
	"fmt"
	"runtime"
)
const (
	cnt =2 //併發處理的數量
)
var vcnt int
func begin(id string, in chan<- string) {
	in<- fmt.Sprintf("set in chan  %s",id)
	fmt.Println("in begin, in chan ",id)
	vcnt++
	if vcnt >= cnt {
		close(in)
	}
}
func media(in <-chan string,out chan<- string) {
	for d:=range in {
		fmt.Println("in media "+d)
		out<-d
	}
	close(out)
}
func end(out <-chan string,done chan<- int) {
	for d:= range out {
		fmt.Println("in end "+d)
	}
	done<-1
	close(done)
}
func main() {
	maxProcs := runtime.NumCPU() //獲取cpu個數
	runtime.GOMAXPROCS(maxProcs) //限制同時執行的goroutines數量
	vcnt=0
	in := make(chan string,cnt)
	out :=make(chan string)
	done :=make(chan int)
	for i:=0;i<cnt;i++ {
		go begin(string(i+'0'),in)
	}
	go media(in,out)
	go end(out,done)
	<-done
}
在main函式中,首先對同時執行的協程數量進行限定。

三個chan中,in是輸入chan,通過cnt個協程分別進行寫入,對in設定cnt個緩衝區,保證能併發的寫入

out是輸出chan,在media中把in傳遞到out,在end中完成輸出

done是標識chan,用來通知主函式,end協程執行完畢,可以退出了。用sync.WaitGroup是更加通用的做法。

另外,對於chan的close,是告知讀入chan已完成,無新的資料讀入了。