天天看點

Go語言學習筆記-并發

并發與并行的差別:

差別:

1. 并發:☞邏輯上具備同時處理多個任務的能力,指的是多個任務在同一時間段執行而不是同一時刻

2. 并行:☞實體上同一時刻執行多個任務

goroutine:

goroutine像一個多線程和協程的綜合體,運作時會建立多個限制來執行并發任務,且任務單元可排程到其他線程并行執行,最大限度提升執行效率。

go關鍵字

go println("hello world")

go funct(s){
    println(s)
}("hello world")
           

建立并發任務通過go關鍵字就可,但是關鍵字go并非執行并發操作,而是建立一個并發任務單元,放置于系統隊列中等待排程器排程執行。等待執行過程中,目前流程不會阻塞,也不會等待該任務啟動,存在多個任務時也不會去保證并發任務的執行次序。

每個任務單元相比系統線程棧的MB級别來說小了很多,goroutine定義棧初始隻需要2KB。自定義棧采用按需配置設定的政策,在需要時進行擴容,最大能達到GB規模。

go關鍵字與defer一樣,會因為”延遲執行“而立即計算并複制執行參數,可參考下面例子:

package main

import "time"

var c int

func counter() int {
    c++
    return c
}

func main() {
    a :=
    go func(x, y int) {
        time.Sleep(time.Second)
        println("go:", x, y)
    }(a, counter())

    a +=
    println("main:", a, counter())
    time.Sleep(time.Second *)
}

//輸出結果:
main:
go:
           

通道

Go内置CSP模型,且鼓勵使用CSP通道,以通信來代替記憶體共享,實作并發安全,不需要開發人員自行維護資料一緻和完整性。

channel是顯式的,收發雙方必須都知道資料類型和具體通道。

channel從底層實作上來說是一個隊列,同步模式下收發雙方必須配對,然後直接複制資料給對方,配對失敗則置入等待隊列,直到出現适配的另一方

異步模式搶奪的是資料緩沖槽,發送方要求有空草可供寫入,接收方要求有緩沖資料可讀。

通道除了傳遞資料之外,通常也被用作事件通知。

func main(){
  done := make(chan struct{}) //結束事件
  c := make(chan string)     //資料傳輸通道

  go func(){
    s:=<-c        //接受資料
    println(s)
    close(done)   //關閉通道,作為結束事件通知
  }()
  c <- "hi!"    //發送資料
  <-done        //阻塞,置入等待 等待資料或事件通知
}
           

異步模式

可以使用len以及cap函數來擷取緩沖區的大小以及緩沖區已緩沖的數量

對于同步模式的channel使用len以及cap傳回結果均為0,此不同可用作區分channel是同步還是異步

import "unsafe"
func main(){
  c := make(chan int)       //建立一個帶3個緩沖槽的異步通道
  c
  c
  println("通道中第一個值:    ",<-c)   //取出第一個資料
  println("通道中第二個值:    ",<-c)   //取出第二個資料
  println("通道中寫入值的數量:    ",len(c))
  println("通道的容積:    ",cap(c))
  println("通道變量的位址:    ",c,"通道的長度:    ",unsafe.Sizeof(c))
}

//輸出
//通道中第一個值:     1
//通道中第二個值:     2
//通道中寫入值的數量:     0
//通道的容積:     3
//通道變量的位址:     0xc42006a000 通道的長度:     8