關於golang的協程並行的控制與示例程序

首先明確一個觀點並行 併發區別:

並行是指程序的運行狀態,要有兩個線程正在執行才能算是Parallelism;併發指程序的邏輯結構,Concurrency則只要有兩個以上線程還在執行過程中即可。簡單地說,Parallelism要在多核或者多處理器情況下才能做到,而Concurrency則不需要。golang 利用 go func() 的方式,可以進行多個函數的並行。

我們寫C 的時候,假如用到多進程,我們通常都會用信號,管理等來進程進程間的通信, 那麼golang是怎麼實現這個的呢?? 直接看碼說話吧

package main

import (
  "fmt"
  "time"
)

func main() {
  timeout := make(chan bool, 1)
  go func() {
    fmt.Println("------------ channel 1--------------")
    t1 := time.Now().UnixNano()
    fmt.Println(t1)
    fmt.Println("這個一定會執行")
    
    time.Sleep(3 * time.Second)
    // timeout <- true
    timeout <- true
  }()
  
  fmt.Println("首先邏輯還是響應 main 函數")
  
  go func() {
    fmt.Println("------------ channel  2--------------")
    t2 := time.Now().UnixNano()
    fmt.Println(t2)
    fmt.Println("相當於fork一個子進程在進行")
  }()
  
  ch := make(chan int)
  select {
    case <-ch:
    case <-timeout:
      fmt.Println("------------ 回到main函數 --------------")
      fmt.Println("task is timeout!")
  }
  
  fmt.Println("main 函數本身的輸出")
}

我們執行代碼看一看結果

首先邏輯還是響應 main 函數
------------ channel 2--------------
1471577916141068800
相當於fork一個子進程在進行
------------ channel 1--------------
1471577916142068800
這個一定會執行
------------ 回到main函數 --------------
task is timeout!
main 函數本身的輸出

分別從 納秒的時間戳可以看出, 兩個 go func() 幾乎是同時執行的, 這種是golang並行處理的寫法,  goroutine是Go語言運行庫的功能,不是操作系統提供的功能,goroutine不是用線程實現的。, golang同樣提供了一種監視手段去監視每個並行處理邏輯的返回, select就是這種手段

按照目前golang的機制,假如調用select的話,循環監控,假如我們註釋掉 timeout <- true 這句, 看看會有什麼變化, 我們再執行  go run xx.go 的時候, 會提示 fatal error: all goroutines are asleep - deadlock!,  這是可以理解爲我們的 select 監控的多個並行狀態都沒有回調響應,所以程序一直在等待,造成死鎖導致了錯誤。

其實golang裏面也可以用 sync的  waitgroup 進行同步鎖,但是這個跟協程並行似乎關係不大,有興趣的也可以瞭解下

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