這是一個建立於 的文章,其中的資訊可能已經有所發展或是發生改變。
go從語言層面就支援並行程式設計
goroutine(Go語言並行設計的核心),比thread高效易用
package mainimport( "fmt" "runtime")func say(word string){ for i:=0; i<10; i++ {// runtime.Gosched() //讓出時間片 fmt.Println(word) }}func main(){ //預設系統線程數量為1,可通過下面指令調整,充分利用多核優勢 runtime.GOMAXPROCS(4) go say("Hello") say("World")}
多個 goroutine 運行在同一個進程裡面,共用記憶體資料,不過設計上我們要遵循:不要通過共用來通訊,而要通過通訊來共用
go提供了channel作為資料通訊,類似unix下的管道,需要用make定義通訊資料類型
package mainimport( "fmt" "runtime")//send函數讀取channel時不會讀取到自己發送到channel的資料func send(name string,c chan string){ w := "Hello " + name //send message w to channel c c <- w //recv message from c w = <- c fmt.Printf("A Got %v from recv\n",w)}func recv(c chan string){ //recv message from c w := <- c fmt.Printf("B Got %v from send\n",w) //send message to c c <- "OK."}func main(){ runtime.GOMAXPROCS(4) c := make(chan string) go send("B",c) //go recv(c) res := "" fmt.Scan(&res)}
channel 接收和發送資料都是阻塞的,除非另一端已經準備好,這樣就使得Goroutines 同步變的更加的簡單,而不需要顯式的 lock。
有緩衝的channel
ch := make(chan type, value)
value == 0 ! 無緩衝(阻塞)
value > 0 ! 緩衝(非阻塞,直到 value 個元素)
生產者通過關鍵字 close 函數關閉 channel,關閉channel 之後就無法再發送任何資料了,在消費方可以通過文法 v, ok := <-ch 測試 channel是否被關閉。如果 ok 返回 false,那麼說明 channel 已經沒有任何資料並且已經被關閉。
通過select在多個channel之間隨機播放一個處理
package mainimport( "fmt") func main(){ chan_a := make(chan string) chan_b := make(chan string) chan_quit := make(chan string) go func() { //從chan_a通道接收資料五次,然後發送quit命令 for i:=0;i<5;i++ { fmt.Println("Listen on chan_a",<-chan_a) } chan_quit <- "quit" }() go func() { //同上 for i:=0;i<5;i++ { fmt.Println("Listen on chan_b",<-chan_b) } chan_quit <- "quit" }() for { select { case chan_a <- "hello_a"://chan_a通道可寫 fmt.Println("Send hello_a to chan_a") case chan_b <- "hello_b"://chan_b通道可寫 fmt.Println("Send hello_b to chan_b") case <- chan_quit://chan_quit通道可讀 fmt.Println("Quit") return //case <- time.After(5 * time.Second): //設定逾時 //default: //當所有channel都阻塞時調用預設代碼 } } }