併發

Go語言的併發是是指goroutine運行時是相互獨立的,能讓某個函數獨立於其他函數運行。

併發不是並行。並行是讓不同的代碼片段同時在不同的物理處理器上執行。並行的關鍵是同時做很多事情,而併發是指同時管理很多事情,這些事情可能只做了一半就被暫停去做別的事情了。


Go的併發同步模型來自通信順序進程(Communicating Sequential Processes,CSP)的範型。CSP是一種消息傳遞模型,通過在goroutine之間傳遞數據。而不需要對數據進行加鎖來實現同步訪問。

通道(channel)用於goroutine之間同步和傳遞數據的數據類型。


goroutinue本質上是協程,但有兩點不同:

  1. goroutinue可實現並行;多個協程可在多個處理器同時跑。而協程同一時刻只能在一個處理器跑。
  2. goroutinue之間的通信是通過channel(消息隊列);而協程的通信是通過yield和resume()操作。

---------------------------------

當一個正在運行的goroutine需要執行一個系統調用,如打開一個文件,線程會和goroutine從邏輯處理器上分離,該線程會繼續阻塞,等待系統調用的返回。與此同時,調度器會創建一個新線程,並將其綁定在邏輯處理器上。

之後,調度器會從本地運行隊列裏選擇另一個 goroutine 來運行。一旦被阻塞的系統調用執行完成並返回,對應的 goroutine 會放回到本地運行隊列,而之前的線程會保存好,以便之後可以繼續使用。


    WaitGroup是計數信號量,可以用來維護運行的goroutine。

//wg用來等待程序完成
//計數加2,表示等待兩個goroutine
var wg sync.WaitGroup
wg.Add(2)

修改邏輯處理器數量

runtime 提供了修改 Go 語言運行時配置參數的能力。

runtime.GOMAXPROCS(runtime.NumCPU())



通道

    通過使用管道發送和接收需要共享的資源,在goroutine之間做同步。

聲明通道時,需要指定將要被共享的數據的類型。可共享內置類型、命名類型、結構類型、引用類型或指針。

使用make創建管道,

//無緩衝的整形管道
unbuffered := make(chan int)

//無緩衝的字符串通道
buffered := make(chan string, 10)

    make的第一個參數需要是關鍵字chan,之後跟着允許通道交換的數據類型。

    向通道發送值或指針需要用到<-操作符。


無緩衝的通道(unbuffered channel):指在接收前沒有能力保存任何值。要求發送goroutine和接收goroutine同時準備好,才能進行發送和接收操作。

如果兩個foroutine同時沒有準備好,通道會導致先執行發送或接收操作的goroutine阻塞。


有緩衝的通道(buffered channel):是一種在被接收前能存儲一個或者多個值的通道。

不強制要求 goroutine 之間必須同時完成發送和接收。

只有在通道中沒有要接收的值時,接收動作纔會阻塞。


兩者區別:

    無緩衝的通道保證進行發送和接收的 goroutine 會在同一時間進行數據交換;有緩衝的通道沒有這種保證。






















發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章