用go寫一個docker(2)-go的Goroutine和通道
阿新 • • 發佈:2020-12-18
如果熟悉go的話請關掉這篇文章,不用往下讀了。
併發和並行
併發強調的是可同時做多個事情(非阻塞),並行強調的是同一時間內多個事情同時進行。
可以用CPU多核來理解:在單核CPU中,系統是可併發的,我們可以在開啟瀏覽器的同時開啟播放器聽歌。CPU分了很多時間片,輪流給各程序使用,這些程序“看起來像”同時執行,但同一時間內只有一個時間片。而要並行的話則必須要多核CPU,因為並行強調的是同一時間內多個程序同時執行,即同一時間內要多個時間片。簡而言之:單核CPU的並行能力是0,N核CPU的並行能力是N。
阻塞和非阻塞
如下程式碼就是阻塞的:
package main import ( "fmt" "time" ) func Sleep(i int){ time.Sleep(time.Second * time.Duration(i)) fmt.Println("sleep second ", i) } func main() { for i:=1; i < 4; i++ { Sleep(i) } fmt.Println("main") }
Sleep函式執行完後,才執行fmt.Println(“main”)。
在Sleep(i)前加一個關鍵字go,該程式碼就變成非阻塞的了。
for i:=1; i < 4; i++ {
go Sleep(i)
}
Goroutine
go是一個在語言層面就支援併發的程式語言,最基本的執行單元是goroutine,類似於協程(coroutine),goroutine可以理解為go的協程。
要使用goroutine很簡單,直接在函式呼叫前加go即可:
package main import ( "fmt" "time" ) func Sleep(i int){ time.Sleep(time.Second * time.Duration(i)) fmt.Println("sleep second ", i) } func Sleep2() { time.Sleep(time.Second * time.Duration(2)) fmt.Println("sleep 2") } func main() { for i:=1; i < 4; i++ { go Sleep(i) } go Sleep2() fmt.Println("main") time.Sleep(time.Second * time.Duration(4)) }
通道
很多程式語言使用共享記憶體來傳遞多執行緒間的資料,go受CSP論文的啟發,還實現了另一種方式:使用通道來傳遞-channel。
go的channel使用很簡單:通過make建立一個channel;通過<-channel獲取通道資料;通過channel<-msg傳送資料到通道中:
package main import ( "fmt" "time" ) func Reader(c chan string) { // 讀取channel資料 msg := <-c fmt.Println("Reader", msg) } func Sender(c chan string, msg string) { // 傳送資料到channel c <- msg + " from Sender" } func main() { c := make(chan string) go Reader(c) go Sender(c, "hello") time.Sleep(time.Second * 1) }
Goroutine和通道是go併發的基石,有興趣的話可以深入一下。
go的介紹就到這裡,接下來開始介紹Linux系統中和docker相關的知識了。