1. 程式人生 > 其它 >用go寫一個docker(2)-go的Goroutine和通道

用go寫一個docker(2)-go的Goroutine和通道

技術標籤:後端運維go

如果熟悉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相關的知識了。