首先明確一個觀點並行 併發區別:
並行是指程序的運行狀態,要有兩個線程正在執行才能算是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 進行同步鎖,但是這個跟協程並行似乎關係不大,有興趣的也可以瞭解下