中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Go協程實現原理和使用分析是怎樣的

發布時間:2021-11-10 09:40:54 來源:億速云 閱讀:197 作者:柒染 欄目:大數據

這期內容當中小編將會給大家帶來有關 Go協程實現原理和使用分析是怎樣的,文章內容豐富且以專業的角度為大家分析和敘述,閱讀完這篇文章希望大家可以有所收獲。

Go 并發編程原理

Go 語言的協程實現被稱之為 goroutine,由 Go 運行時管理,在 Go 語言中通過協程實現并發編程非常簡單:我們可以在一個處理進程中通過關鍵字 go 啟用多個協程,然后在不同的協程中完成不同的子任務,這些用戶在代碼中創建和維護的協程本質上是用戶級線程,Go 語言運行時會在底層通過調度器將用戶級線程交給操作系統的系統級線程去處理,如果在運行過程中遇到某個 IO 操作而暫停運行,調度器會將用戶級線程和系統級線程分離,以便讓系統級線程去處理其他用戶級線程,而當 IO 操作完成,需要恢復運行,調度器又會調度空閑的系統級線程來處理這個用戶級線程,從而達到并發處理多個協程的目的。此外,調度器還會在系統級線程不夠用時向操作系統申請創建新的系統級線程,而在系統級線程過多的情況下銷毀一些空閑的線程,這個過程和 PHP-FPM 的工作機制有點類似,實際上這也是很多進程/線程池管理器的工作機制,這樣一來,可以保證對系統資源的高效利用,避免系統資源的浪費。

以上,就是 Go 語言并發編程的獨特實現模型。

協程簡單示例

下面通過一個簡單的示例來演示如何在 Go 語言中通過協程進行并發編程,我們在 add.go 中編寫一個加法函數 add并通過協程的方式來調用它:

package main
import "fmt"
func add(a, b int) {    var c = a + b;    fmt.Printf("%d + %d = %d", a, b, c)}
func main() {    go add(1, 2)}

嗯,就是這么簡單,在這段代碼中包含了兩個協程,一個是顯式的,通過 go 關鍵字聲明的這條語句,表示啟用一個新的協程來處理加法運算,另一個是隱式的,即 main 函數本身也是運行在一個主協程中,該協程和調用 add 函數的子協程是并發運行的兩個協程,就好比從 go 關鍵字開始,從主協程中叉出一條新路。和之前不使用協程的方式相比,由此也引入了不確定性:我們不知道子協程什么時候執行完畢,運行到了什么狀態。在主協程中啟動子協程后,程序就退出運行了,這就意味著包含這兩個協程的處理進程退出了,所以,我們運行這段代碼,不會看到子協程里運行的打印結果,因為還沒來得及執行它們,進程就已經退出了。另外,我們也不要試圖從 add 函數返回處理結果,因為在主協程中,根本獲取不到子協程的返回值,從子協程開始執行起就已經和主協程沒有任何關系了,返回值會被丟棄。

如果要顯示出子協程的打印結果,一種方式是在主協程中等待足夠長的時間再退出,以便保證子協程中的所有代碼執行完畢:

package main
import (    "fmt"    "time")
func add(a, b int) {    var c = a + b;    fmt.Printf("%d + %d = %d\n", a, b, c)}
func main() {    go add(1, 2)    time.Sleep(1e9)}

這里,我們通過 time.Sleep(1e9) 讓主協程等待 1s 后退出,這樣,運行 go run add.go 就可以看到打印結果了:

Go協程實現原理和使用分析是怎樣的

不過,這種方式過于簡單粗暴,對于加法運算,1s 肯定夠了(而且根本不需要這么長時間),但是如果是數據庫連接、發送郵件之類的難以預估時間的操作呢?這種方式就不合適了,我們需要一種更精準的方式在子協程執行完畢后,立即退出主協程,這就涉及到協程間的通信,我們將在下一篇教程中重點討論這一塊,并且通過協程間通信來重寫這段代碼。

并發執行示例

目前為止,我們僅僅演示了 Go 語言協程的啟動和簡單使用,但是通過上述代碼還不足以驗證協程是并發執行的,接下來,我們通過下面這段代碼來驗證協程的并發執行:

package main
import (    "fmt"    "time")
func add(a, b int) {    var c = a + b;    fmt.Printf("%d + %d = %d\n", a, b, c)}
func main() {    for i := 0; i < 10; i++ {        go add(1, i)    }    time.Sleep(1e9)}

很簡單,我們給協程代碼外層套上一個循環就可以了,這樣一來,就同時啟動了 10 個子協程,由于它們是并發執行的,執行的先后順序無法保證,所以我們就看到了這樣的打印結果:

Go協程實現原理和使用分析是怎樣的

如果你還不放心,可以在 add 函數最后添加如下這段代碼:

time.Sleep(3e9)

表示每個子協程中執行完打印語句睡眠 3 秒再退出,如果不是并發執行,那么肯定至多只能打印一條結果出來,但實際情況是,仍然是打印 10 條結果,并且沒有任何延遲,證明這些加法運算是并發執行的。

上述就是小編為大家分享的 Go協程實現原理和使用分析是怎樣的了,如果剛好有類似的疑惑,不妨參照上述分析進行理解。如果想知道更多相關知識,歡迎關注億速云行業資訊頻道。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

南乐县| 尼勒克县| 永善县| 满洲里市| 云南省| 太原市| 高邮市| 新余市| 乐昌市| 双流县| 和林格尔县| 濮阳县| 青神县| 安溪县| 南和县| 蕲春县| 大化| 巴林右旗| 申扎县| 保亭| 普兰店市| 郧西县| 杂多县| 平泉县| 呼和浩特市| 长沙县| 丁青县| 宣汉县| 化州市| 海阳市| 宁都县| 定兴县| 同德县| 潢川县| 鄂托克前旗| 双辽市| 平山县| 吴川市| 贡嘎县| 启东市| 揭西县|