go 語言併發機制 goroutine 初探

2022-02-11 18:35:31 字數 1152 閱讀 7524

go 語言的乙個很大的優勢就是可以方便地編寫併發程式。go 語言內建了 goroutine 機制。這是一種類似 coroutaine(協程) 的東西。但是又不完全相同。

比如這個例子:

package main import (     "fmt";     "strconv" ) func main()  func task(name string, ch chan int)          ch <- 1     }(); }
執行以後,發現會 a b 兩個 goroutine 會交替執行,並像傳統的協程需要手動 schedule 。看起來很神奇。

稍稍改一下**,把

fmt.printf("%s %d\n", name, i)
改成

print(name + " " + strconv.itoa(i) + "\n")
再看看。神奇的效果消失了,只有 a 被執行。

那麼 fmt.printf 和 print 有什麼差別,導致了這個結果呢?

大致翻了一下 go 的**,看出 go 語言在對 c lib 的包裝上用了個 cgo 的方式。而在通過 cgo 呼叫 c 庫的時候,會在呼叫時自動 schedule 切換走,在呼叫結束的時候再返回。這兩個結果的差異就在於,fmt.printf 是通過 cgo 包裝的,而 print 則是原生實現的。所以在呼叫 fmt.printf 的時候,就自動實現了排程。

傳統的 coroutaine 在訪問網路、資料庫等 io 操作時仍然會阻塞,失去併發能力,所以通常需要結合非同步 io 來實現。而現有的庫如果本身未提供非同步功能,就很難辦,往往需要重新實現。而且,即使有非同步 io 功能,也需要額外的開發,才能在表現上和以往順序程式相同的方式。

go 語言的這種實現方式很好的解決了這個問題,可以充分利用現有的大量 c 庫來包裝。

同時,也還是可以使用 runtime.gosched() 來手動排程。在運算量大的場景下,也還是必要的。

在使用 print 的例子裡,如果使用 runtime.gomaxprocs(2),又可以重新並行起來。這時,兩個 goroutine 是在兩個獨立的執行緒中執行的。這又是 goroutine 和協程的乙個不同點。不過啟用多個執行緒並不見得能讓程式更快。因為跨執行緒的上下文切換代價也是很大的。在上面那個簡單的例子裡,還會讓程式變得更慢。降低 上下文切換開銷也是協程的乙個優勢所在。

Go語言併發

協程 本質上是一種使用者態執行緒,不需要作業系統來進行搶占式排程,且在真正的實現重寄存於執行緒中,因此,系統開銷極小,可以有效提高執行緒的任務併發性,從而避免多執行緒的缺點。使用協程的優點是程式設計簡單,結構清晰 缺點是需要語言的支援。協程最大優勢 輕量級 可以輕鬆建立上百萬個而不會導致系統資源衰竭...

Go語言 併發篇

go語言 併發篇 2012 06 06 09 55 by 軒脈刃,當被問到為什麼用go語言,一定不得不提的是go語言的併發程式編寫。在c語言中編寫非常繁瑣複雜的併發程式在go語言中總是顯得如此便捷。go中併發程式依靠的是兩個 goroutine和channel 對於初學者,goroutine直接理解...

Go語言基礎 併發

並行 多件事在同一時刻發生。併發 多件事在同一時間間隔發生。摘自 和 concurrent and parallel programming 上文如果用程式設計師的語言來講,cpu處理器相當於上圖的咖啡機的角色,任務相當於佇列中的人。一定要仔細閱讀此文 這篇文章提到了網路伺服器併發連線數 吐吞量 寬...