Go協程的調用與原理

Goroutine

Go不需要像C++或者Java那樣手動管理線程,Go語言的goroutine機制自動幫你管理線程。

使用goroutine、

Go語言中使用goroutine非常簡單,只需要在調用函數的時候在前面加上go關鍵字,就可以為一個函數創建一個goroutine。

一個goroutine必定對應一個函數,可以創建多個goroutine去執行相同的函數

啟動單個goroutine

在調用的函數前加上一個go關鍵字,就可以啟動一個goroutine

func hello() {fmt.Println("Hello Goroutine!")
}
func main() {hello()fmt.Println("main goroutine done!")
}

這個示例中hello函數和下面的語句是串行的,執行的結果是打印完Hello Goroutine!后打印main goroutine done!。

接下來我們在調用hello函數前面加上關鍵字go,也就是啟動一個goroutine去執行hello這個函數。

func main() {go hello() // 啟動另外一個goroutine去執行hello函數fmt.Println("main goroutine done!")
}
```..
這一次的執行結果只打印了main goroutine done!,并沒有打印Hello Goroutine!。為什么呢?在程序啟動時,Go程序就會為main()函數創建一個默認的goroutine。當main()函數返回的時候該goroutine就結束了,所有在main()函數中啟動的goroutine會一同結束,main函數所在的goroutine就像是權利的游戲中的夜王,其他的goroutine都是異鬼,夜王一死它轉化的那些異鬼也就全部GG了。所以我們要想辦法讓main函數等一等hello函數,最簡單粗暴的方式就是time.Sleep了。```go
func main() {go hello() // 啟動另外一個goroutine去執行hello函數fmt.Println("main goroutine done!")time.Sleep(time.Second)
}

執行上面的代碼你會發現,這一次先打印main goroutine done!,然后緊接著打印Hello Goroutine!。

首先為什么會先打印main goroutine done!是因為我們在創建新的goroutine的時候需要花費一些時間,而此時main函數所在的goroutine是繼續執行的。

啟動多個goroutine

來看下面這個代碼:

var wg sync.WaitGroupfunc hello(i int) {defer wg.Done() // goroutine結束就登記-1fmt.Println("Hello Goroutine!", i)
}
func main() {for i := 0; i < 10; i++ {wg.Add(1) // 啟動一個goroutine就登記+1go hello(i)}wg.Wait() // 等待所有登記的goroutine都結束
}

多次執行上面的代碼,會發現每次打印的數字的順序都不一致。這是因為10個goroutine是并發執行的,而goroutine的調度是隨機的

如果主協程退出了,其他任務還執行嗎(運行下面的代碼測試一下吧)

package mainimport ("fmt""time"
)func main() {// 合起來寫go func() {i := 0for {i++fmt.Printf("new goroutine: i = %d\n", i)time.Sleep(time.Second)}}()i := 0for {i++fmt.Printf("main goroutine: i = %d\n", i)time.Sleep(time.Second)if i == 2 {break}}
}

在這里插入圖片描述

是停止的

goroutine與線程

可增長的棧

OS線程(操作系統線程)一般都有固定的棧內存(通常為2MB),一個goroutine的棧在其生命周期開始時只有很小的棧(典型情況下2KB),goroutine的棧不是固定的,他可以按需增大和縮小,goroutine的棧大小限制可以達到1GB,雖然極少會用到這個大。所以在Go語言中一次創建十萬左右的goroutine也是可以的。

goroutine的調度

GPM是Go語言運行時(runtime)層面的實現,是go語言自己實現的一套調度系統。區別于操作系統調度OS線程。

  1. G很好理解,就是個goroutine的,里面除了存放本goroutine信息外 還有與所在P的綁定等信息。
  2. P管理著一組goroutine隊列,P里面會存儲當前goroutine運行的上下文環境(函數指針,堆棧地址及地址邊界),P會對自己管理的goroutine隊列做一些調度(比如把占用CPU時間較長的goroutine暫停、運行后續的goroutine等等)當自己的隊列消費完了就去全局隊列里取,如果全局隊列里也消費完了會去其他P的隊列里搶任務。
  3. M(machine)是Go運行時(runtime)對操作系統內核線程的虛擬, M與內核線程一般是一一映射的關系, 一個groutine最終是要放到M上執行的;
    P與M一般也是一一對應的。他們關系是: P管理著一組G掛載在M上運行。當一個G長久阻塞在一個M上時,runtime會新建一個M,阻塞G所在的P會把其他的G 掛載在新建的M上。當舊的G阻塞完成或者認為其已經死掉時 回收舊的M。

P的個數是通過runtime.GOMAXPROCS設定(最大256),Go1.5版本之后默認為物理線程數。 在并發量大的時候會增加一些P和M,但不會太多,切換太頻繁的話得不償失。

單從線程調度講,Go語言相比起其他語言的優勢在于OS線程是由OS內核來調度的,goroutine則是由Go運行時(runtime)自己的調度器調度的,這個調度器使用一個稱為m:n調度的技術(復用/調度m個goroutine到n個OS線程)。 其一大特點是goroutine的調度是在用戶態下完成的, 不涉及內核態與用戶態之間的頻繁切換,包括內存的分配與釋放,都是在用戶態維護著一塊大的內存池, 不直接調用系統的malloc函數(除非內存池需要改變),成本比調度OS線程低很多。 另一方面充分利用了多核的硬件資源,近似的把若干goroutine均分在物理線程上, 再加上本身goroutine的超輕量,以上種種保證了go調度方面的性能。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/77089.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/77089.shtml
英文地址,請注明出處:http://en.pswp.cn/web/77089.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

自然語言處理(9)—— 共現詞矩陣及Python實現

共現詞矩陣 1. 概述2. 構建步驟3. 代碼實現&#xff08;Python&#xff09;結語 共現詞矩陣&#xff08;Co-occurrence Matrix&#xff09;是自然語言處理&#xff08;NLP&#xff09;中用于捕捉詞語間語義關系的重要工具。共現矩陣通過統計詞語在特定上下文窗口內的共現頻率&a…

Spark SQL核心解析:大數據時代的結構化處理利器

在大數據處理領域&#xff0c;Spark以其強大的分布式計算能力脫穎而出&#xff0c;而Spark SQL作為Spark生態系統的重要組成部分&#xff0c;為結構化和半結構化數據處理提供了高效便捷的解決方案。它不僅整合了傳統SQL的強大查詢功能&#xff0c;還深度集成到Spark的計算框架中…

多態以及多態底層的實現原理

本章目標 1.多態的概念 2.多態的定義實現 3.虛函數 4.多態的原理 1.多態的概念 多態作為面對三大特性之一,它所指代的和它的名字一樣,多種形態.但是這個多種形態更多的指代是函數的多種形態. 多態分為靜態多態和動態多態. 靜態多態在前面已經學習過了,就是函數重載以及模板,…

linux下開發NFC讀寫器

linux下使用NFC讀卡器&#xff0c;基于QT5開發 創建工程&#xff0c;引入lib開始編寫代碼 創建工程&#xff0c;引入lib 創建一個QT工程&#xff0c;如果是控制臺程序&#xff0c;則去掉gui QT - gui引入lib庫 LIBS -L$$PWD/lib -lyw60x這里需要將libyw60x.so庫文件放在工程…

Linux基礎使用-筆記

1. 文件和目錄操作 查看當前目錄&#xff1a;pwd 命令用于顯示當前工作目錄的完整路徑。 pwd切換目錄&#xff1a;cd 命令用于切換工作目錄。 # 切換到指定目錄 cd /home/user/Documents # 切換到上一級目錄 cd .. # 切換到用戶主目錄 cd ~列出目錄內容&#xff1a;ls 命令用…

DAG(有向無環圖)計算模型面試內容整理-拓撲排序(Topological Sort)和節點依賴與并行度

拓撲排序(Topological Sort) 拓撲排序(Topological Sort): 拓撲排序是針對有向無環圖(DAG)的一種線性排序方法。這種排序方法的特點是,對于DAG中的每一條有向邊 (A → B),在拓撲排序中節點A總是排在節點B之前。

23種設計模式-結構型模式之享元模式(Java版本)

Java 享元模式&#xff08;Flyweight Pattern&#xff09;詳解 &#x1f98b; 什么是享元模式&#xff1f; 享元模式是一種結構型模式&#xff0c;它通過共享相同的對象來減少內存消耗&#xff0c;適用于大量細粒度對象的場景。關鍵思想是緩存重復出現的對象&#xff0c;避免…

瀏覽器訪問背后的秘密:從加載到關閉,數據是否會丟失?

? 一次瀏覽器訪問 www.xxx.com 背后發生了什么&#xff1f; —— 以及“我點了 &#xff0c;數據會不會丟&#xff1f;”的深度剖析 適讀人群&#xff1a;Web 開發者、運維工程師、性能調優/安全從業者 1?? 打開瀏覽器敲下網址&#xff1a;鏈路是如何啟動的&#xff1f; 階…

【HDFS入門】深入解析DistCp:Hadoop分布式拷貝工具的原理與實踐

目錄 1 DistCp概述與應用場景 2 DistCp架構設計解析 2.1 系統架構圖 2.2 執行流程圖 3 DistCp核心技術原理 3.1 并行拷貝機制 3.2 斷點續傳實現原理 4 DistCp實戰指南 4.1 常用命令示例 4.2 性能優化策略 5 異常處理與監控 5.1 常見錯誤處理流程 5.2 監控指標建議…

hbuilderx云打包生成的ipa文件如何上架

使用hbuilderx打包&#xff0c;會遇到一個問題。開發的ios應用&#xff0c;需要上架到app store&#xff0c;因此&#xff0c;就需要APP store的簽名證書&#xff0c;并且還需要一個像xcode那樣的工具來上架app store。 我們這篇文章說明下&#xff0c;如何在windows電腦&…

第十五屆藍橋杯 2024 C/C++組 拼正方形

目錄 題目&#xff1a; 題目描述&#xff1a; 題目鏈接&#xff1a; 思路&#xff1a; 思路詳解&#xff1a; 易錯點&#xff1a; 代碼&#xff1a; 代碼詳解&#xff1a; 題目&#xff1a; 題目描述&#xff1a; 題目鏈接&#xff1a; P10898 [藍橋杯 2024 省 C] 拼正…

華為云獲取IAM用戶Token的方式及適用分析

&#x1f9e0; 一、為什么要獲取 IAM 用戶 Token&#xff1f; 我們用一個生活中的比喻來解釋&#x1f447;&#xff1a; &#x1f3e2; 比喻場景&#xff1a; 你要去一個 高級寫字樓&#xff08;華為云物聯網平臺&#xff09; 辦事&#xff08;調用接口管理設備&#xff09;&…

樂聚機器人與地瓜機器人達成戰略合作,聯合發布Aelos Embodied具身智能

要聞 4月19日&#xff0c;在CCF人形機器人與人工智能技術巡回研討會&#xff08;武漢站&#xff09;上&#xff0c;樂聚機器人與地瓜機器人達成戰略合作&#xff0c;雙方將基于RDK X5、RDK S100以及更高性能的國產大算力平臺&#xff0c;就夸父&#xff08;KUAVO&#xff09;、…

Web3架構下的數據隱私與保護

在這個信息爆炸的時代&#xff0c;Web3的概念如同一股清流&#xff0c;以其去中心化的特性&#xff0c;為數據隱私與保護帶來了新的希望。Web3&#xff0c;也被稱作下一代互聯網&#xff0c;它通過區塊鏈技術實現數據的去中心化存儲和處理&#xff0c;旨在提高數據的安全性和隱…

【OceanBase相關】02-OceanBase數據庫NFS備份實踐

文章目錄 一、前言1、概述2、備份方式3、備份流程4、恢復流程二、NFS備份1、注意事項2、服務端配置3、客戶端配置4、備份策略配置三、常用操作四、Q&A1、數據備份任務執行失敗,提示`start log archive backup when not STOP is not supported`1.1、問題說明1.2、解決措施2…

一行命令打開iOS模擬器

要在 Mac 命令行打開 iPhone 15 Pro 模擬器&#xff0c;需滿足已安裝 Xcode 這一前提條件&#xff0c;以下是具體操作步驟&#xff1a; 步驟一&#xff1a;列出所有可用模擬器設備 打開終端&#xff08;Terminal&#xff09;&#xff0c;輸入并執行以下命令&#xff0c;用于列…

Java虛擬機(JVM)家族發展史及版本對比

Java虛擬機&#xff08;JVM&#xff09;家族發展史及版本對比 一、JVM家族發展史 1. 早期階段&#xff08;1996-2000&#xff09; Classic VM&#xff08;Java 1.0-1.1&#xff09;&#xff1a; 廠商&#xff1a;Sun Microsystems&#xff08;Oracle前身&#xff09;。特點&…

嘻游電玩三端客戶端部署實戰:PC + Android + iOS 環境全覆蓋教程

本篇文章將針對“網狐系列嘻游電玩組件”的三端客戶端&#xff08;PC端、安卓端、iOS端&#xff09;進行詳細部署實操講解。文章將以實測部署為核心&#xff0c;提供資源結構說明、平臺適配調整、打包配置、常見問題修復&#xff0c;并輔以必要的關鍵配置代碼。 一、客戶端資源…

LabVIEW實現Voronoi圖繪制功能

該 LabVIEW 虛擬儀器&#xff08;VI&#xff09;借助 MathScript 節點&#xff0c;實現基于手機信號塔位置計算 Voronoi 圖的功能。通過操作演示&#xff0c;能直觀展示 Voronoi 圖在空間劃分上的應用。 各部分功能詳細說明 隨機地形創建部分 功能&#xff1a;根據 “Maximum a…

web刷題筆記

2024isctf ezrce 禁用了一些關鍵字符&#xff0c;查詢函數&#xff0c;系統執行函數&#xff0c;執行函數都有&#xff0c;空格也和斜桿也禁用了&#xff0c;但是其他一些很大一部分字符都沒有禁用&#xff0c;屬于關鍵詞禁用的類型&#xff0c;正常的步驟是去查一下列表&#…