Golang 中 Goroutine 的調度

Golang 中 Goroutine 的調度

Golang 中的 Goroutine 是一種輕量級的線程,由 Go 運行時(runtime)自動管理。Goroutine 的調度基于 M:N 模型,即多個 Goroutine 可以映射到多個操作系統線程上執行。以下是詳細的調度過程和策略:

1. 創建 Goroutine
  • 使用 go 關鍵字可以創建一個新的 Goroutine。例如:
  go func() {// 任務代碼}()
  • 創建 Goroutine 的底層方法是 newproc 函數,該函數會創建一個新的 Goroutine 并將其放入 P 的本地隊列中。如果本地隊列已滿,則放入全局隊列中。
2. 調度器(Scheduler)
  • Go 運行時包含一個調度器,負責管理 Goroutine 的執行。調度器的主要任務是從全局隊列或本地隊列獲取可執行的 Goroutine,并將其分配給可用的線程(M)執行。
  • 調度器采用隊列輪轉法,確保每個 Goroutine 都有機會被執行。具體來說,調度器會從 P 的本地隊列中獲取 Goroutine 執行;如果本地隊列為空,則從全局隊列獲取;如果全局隊列也為空,則從其他 P 的本地隊列中“偷取”一半數量的 Goroutine(稱為 work stealing)。
3. Goroutine 的狀態
  • Goroutine 可能處于多種狀態,包括 _Grunning(正在運行)、_Gwaiting(等待中)、_Gblocked(阻塞中)等。
  • 當一個 Goroutine 完成其任務后,會調用 goexit 函數,該函數會將當前 Goroutine 放入 P 的復用鏈表中,并調用 schedule() 函數繼續調度下一個 Goroutine。
4. 搶占式調度
  • Go 調度器是搶占式的,每個 Goroutine 最多執行 10ms 后會被替換。如果 Goroutine 運行超過 10ms,調度器會設置“搶占標志位”,但這一機制僅在有函數調用的情況下生效。
  • 當 Goroutine 發生阻塞(如等待通道、垃圾回收、sleep 休眠、鎖等待、IO 阻塞等),調度器會將當前 Goroutine 調度走,讓其他 Goroutine 來執行。
5. 調度時機
  • 調度時機包括但不限于:Goroutine 完成任務、發生阻塞、系統調用、垃圾回收等。
  • sysmon 是一個專門用于監控和管理 Goroutine 的線程,它記錄所有 P 的 G 任務數量,并使用 schedtick 變量進行計數。如果 schedtick 一直沒有遞增,說明該 P 一直在執行同一個任務;如果持續超過 10ms,則會在該 G 任務的棧信息上加一個標記,G 任務在執行時檢查此標記并中斷自己,將自己添加到隊列末尾,等待下一個 G 任務執行。
6. 核心數據結構
  • Go 運行時維護了三個核心數據結構:G(Goroutine)、P(Processor)、M(Machine)。
    • G 表示 Goroutine,每個 Goroutine 對應一個 G 結構體,存儲其運行堆棧、狀態和任務函數。
    • P 表示 Processor,相當于 CPU 核,為 G 提供執行環境。
    • M 是 OS 線程抽象,負責調度任務,代表真正執行計算的資源。
7. 調度流程
  • 當一個程序啟動時,只有一個主 Goroutine 來調用 main 函數。在運行過程中,可以通過 go 關鍵字創建新的 Goroutine。
  • M 需要綁定一個 P 才能被調度執行,并在綁定后進入 schedule 循環,從全局隊列或 P 的本地隊列獲取 Goroutine 并執行。
  • 當 M 執行完一個 Goroutine 后,會調用 goexitgoexit1 函數,保存當前 Goroutine 的上下文,切換到 g0 及其棧,調用傳入的方法。最后,goexit0 函數清零 Goroutine 屬性,狀態從 _Grunning 改為 _Gdead,解綁 M 和 Goroutine,放入隊列,重新調度。

總結

Golang 的 Goroutine 調度機制通過 M:N 模型實現了高效的并發執行。調度器負責管理 Goroutine 的生命周期和執行順序,確保每個 Goroutine 都有機會被執行。通過搶占式調度和 work stealing 策略,Go 運行時能夠高效地利用系統資源,實現高性能的并發編程。

Goroutine 和 OS 線程之間的映射機制是如何工作的?

Goroutine 和 OS 線程之間的映射機制主要通過 Go 運行時的調度器實現,采用 M:N 模型。這種模型允許將多個 goroutine 映射到較少數量的 OS 線程上,從而提高并發執行的效率。

具體來說,Go 運行時內部包含三個關鍵結構:M(Machine,即 OS 線程)、G(Goroutine)和 P(調度上下文)。M 代表真正的內核線程,G 代表用戶態定義的協程,而 P 則負責調度,實現從 N:1 到 N:M 的用戶空間線程與內核空間線程的映射。

在 Go 程序啟動時,會創建一個或多個 OS 線程,并在這些線程上調度執行 goroutine。當一個 goroutine 需要執行時,Go 運行時會從線程池中選出一個可用的 M 或者新建一個 M。當一個 goroutine 阻塞(如進行 I/O 操作)時,Go 運行時可以將 P 轉移到另一個 M 上繼續執行其他 goroutine,從而提高 CPU 的利用率。

此外,Go 運行時還引入了 GOMAXPROCS 配置參數,它決定了 Go 代碼可以同時執行的 OS 線程數量。通過調整該參數,開發者可以優化應用性能,但需平衡過高設置可能導致的資源競爭和上下文切換開銷增加。

Go 調度器在不同操作系統(如 Linux 和 Windows)上的實現差異有哪些?

Go 調度器在不同操作系統(如 Linux 和 Windows)上的實現存在一些差異,主要體現在 I/O 多路復用機制和調度策略上。

  1. I/O 多路復用機制

    • Linux:Go 語言的運行時調度器在 Linux 上使用了 epoll 機制來實現 I/O 多路復用。epoll 是一種高效的事件驅動機制,能夠處理大量并發的網絡連接和 I/O 操作,從而提高系統的性能和響應速度。
    • Windows:在 Windows 上,Go 語言的運行時調度器使用了 IOCP(I/O Completion Port)機制。IOCP 是 Windows 特有的事件驅動機制,同樣能夠高效地處理大量并發的 I/O 操作。
  2. 調度策略

    • Linux:Linux 的進程調度器將線程作為最小調度單位,通過調度類的概念引入不同的調度策略來平衡低延時和實時性的問題。
    • Go 調度器:Go 調度器在用戶層建立了新的模型,以 Goroutine 作為最小調度單位。這種設計使得 Go 調度器能夠在用戶態進行調度,減少了操作系統線程調度和上下文切換的開銷。此外,Go 調度器還采用了工作竊取(Work Stealing)的方式,通過運行隊列進行分區,平衡不同 CPU 或線程上的運行隊列。
  3. 系統調用處理

    • Linux:Linux 系統調用通常由內核直接處理,而 Go 調度器需要通過用戶態的機制來處理這些系統調用,例如使用 epoll 來處理網絡請求和 I/O 操作。
    • Windows:在 Windows 上,Go 調度器使用 IOCP 來處理系統調用,這同樣是一種高效的事件驅動機制,能夠有效地處理大量并發的 I/O 操作。
  4. 調度器架構的演變

    • 早期 Go 調度器:最早期的 Go 調度器(Go 1 之前)甚至不能很好地支持多線程,最大 M 數為 1。這個版本的調度器在 Linux 上實現,但在其他操作系統上的支持并不完善。
    • 現代 Go 調度器:從 Go 1.1 起,引入了工作竊取調度器,大大提高了調度效率和并發性能。現代 Go 調度器在不同操作系統上都進行了優化,以適應各自的 I/O 多路復用機制和調度策略。

綜上所述,Go 調度器在不同操作系統上的實現差異主要體現在 I/O 多路復用機制和調度策略上。Linux 上使用 epoll,而 Windows 上使用 IOCP

如何優化 Go 程序中的 Goroutine 使用以提高性能?

優化 Go 程序中的 Goroutine 使用以提高性能,可以從以下幾個方面進行:

  1. 合理控制 Goroutine 數量

    • 過多的 Goroutine 會導致系統資源的過度消耗,甚至引發 Goroutine 泄露問題。因此,應根據實際需求合理控制 Goroutine 的數量,避免過度并發。
    • 使用 Goroutine 池化技術可以減少 Goroutine 的創建和銷毀開銷,從而提高性能。
  2. 優化 Channel 的使用

    • Channel 是 Goroutine 之間通信的主要方式,但 Channel 的傳遞大數據會帶來值拷貝的開銷。因此,盡量避免在 Channel 中傳遞大數據。
    • 使用 Channel 時,應盡量避免阻塞和死鎖問題,確保 Channel 的使用高效且安全。
  3. 減少鎖的使用

    • 鎖是并發編程中常見的同步機制,但過度使用鎖會導致性能下降。Go 推薦使用 Channel 的方式調用而不是共享內存,因為 Channel 之間存在大鎖,可以降低鎖的競爭力度。
    • 無鎖編程通過原子操作減少鎖的使用,可以進一步提升并發性能。
  4. 使用 Context 控制 Goroutine 生命周期

    • 設置超時和使用 context.WithTimeout 可以有效管理 Goroutine 的生命周期,避免 Goroutine 泄露。
  5. 減少系統調用

    • Goroutine 的實現是通過同步模擬異步操作,建議將同步調用隔離到可控 Goroutine 中,而不是直接高并發調用。
  6. 使用性能分析工具

    • 使用 Go 提供的性能分析工具如 pprof 和 trace,可以幫助檢測 Goroutine 的運行時間、資源占用等,從而對 Goroutine 的創建和管理進行優化。
  7. 合理設置 GOMAXPROCS

    • GOMAXPROCS 控制了 Go 運行時可以使用的最大工作線程數。合理設置 GOMAXPROCS 可以提高并發性能。
  8. 避免內存泄漏

    • 在使用切片和映射時要合理設置容量,避免內存泄漏。
Goroutine 的搶占式調度機制具體是如何實現的?

Goroutine 的搶占式調度機制在 Go 語言中是通過多種方式實現的,主要包括基于協作的搶占和基于信號的搶占。以下是詳細的實現機制:

  1. 基于協作的搶占

    • Goroutine 棧保護:每個 Goroutine 都有一個 stackguard0 字段,當該字段被設置為 StackPreempt 時,Goroutine 將被搶占。這個機制確保在函數調用時,調度器可以檢查并觸發搶占。
    • 搶占函數:Go 運行時引入了 preemptonepreemptall 函數,這些函數會設置 Goroutine 的 StackPreempt 標志,從而觸發搶占。
    • 垃圾回收搶占:在垃圾回收階段,運行時會調用 preemptall 函數設置所有處理器上 Goroutine 的 StackPreempt 標志,以確保垃圾回收期間所有 Goroutine 都能被搶占。
    • 長時間運行的 Goroutine 搶占:如果一個 Goroutine 的運行時間超過 10ms,系統監控線程(sysmon)會調用 retakepreemptone 函數進行搶占。
  2. 基于信號的搶占

    • 信號處理:在 Go 1.14 版本中,引入了基于信號的搶占機制。當系統處于特定狀態(如 STW、執行 safe point 函數、sysmon 監控期間等)時,會向線程發送 SIGURG 信號。
    • 搶占處理函數:當線程收到 SIGURG 信號后,會調用 asyncPreempt 函數,將 asyncPreempt 的調用強制插入到用戶當前執行的代碼位置,從而實現真正的搶占。
  3. 系統調用引起的搶占

    • sysmon 線程監控:sysmon 線程負責監控系統資源和調度 Goroutine。當發現某個 Goroutine 執行系統調用時間過長時,會調用 retake 函數進行搶占。
    • 搶占邏輯:在搶占過程中,sysmon 會釋放系統調用線程所綁定的 P(進程),而非阻止線程進行系統調用,而是合理利用資源。
  4. 調度器的搶占流程

    • 搶占時機:搶占式調度在以下場景下觸發:Goroutine 執行時間過長、執行較長的函數調用鏈或棧幀擴展時。
    • 搶占行為:當 Goroutine 被標記為需要搶占時,調度器會將其放入全局可運行隊列中,并更新其狀態為 _Runnable,然后繼續調度其他 Goroutine。

通過上述機制,Go 調度器能夠確保在大部分情況下,不同的 Goroutine 都能獲得均勻的時間片,提高了程序的可靠性和穩定性。

在高并發場景下,Goroutine 的調度策略對系統資源的利用效率有何影響?

在高并發場景下,Goroutine 的調度策略對系統資源的利用效率有顯著影響。以下是詳細的分析:

  1. 搶占式調度:Go 運行時系統實現了搶占式調度,以確保 Goroutine 公平地獲得執行時間。如果一個 Goroutine 長時間占用 CPU(大約 10ms),運行時系統會搶占它,將其放回運行隊列,并允許其他 Goroutine 執行。這種機制可以防止某個 Goroutine 占用過多資源,從而提高整體系統的資源利用率。

  2. 工作竊取算法:當一個 P(邏輯處理器)的本地運行隊列為空時,它會嘗試從其他 P 的本地運行隊列中“偷取” Goroutine,以保持 CPU 的利用率。這種工作竊取算法避免了全局鎖的使用,提高了調度效率,特別是在多核處理器上,可以更好地平衡負載。

  3. 優先級調度:Goroutine 的優先級是由 Go 運行時根據任務的優先級來設置的。優先級高的 Goroutine 會得到更多的資源分配,因此可以更快地執行。然而,在一些高并發場景下,大量請求 Goroutine 和其他工作 Goroutine 數量級差別較大,導致調度不合理,有時會導致調度不均衡。

  4. 資源分配:Goroutine 的資源分配是由 Go 運行時根據任務的資源需求來設置的,包括 CPU 時間片和內存空間等。在高并發場景下,頻繁創建和銷毀 Goroutine 可能會導致垃圾回收(GC)負擔加重,影響系統響應速度。

  5. 鎖競爭和優化:高頻繁的鎖競爭會導致性能瓶頸,特別是在高并發環境下。減少全局鎖的使用和優化鎖的策略可以提高系統的性能。

  6. 用戶態調度:Goroutine 的調度在用戶態進行,避免了內核態的資源爭用和線程管理問題。這種機制使得 Goroutine 的切換更加高效,因為它們不依賴于操作系統提供的線程,而是通過用戶態的切換實現。

  7. GOMAXPROCS 參數:GOMAXPROCS 參數決定了同時可執行的 Goroutine 數量,默認值為 CPU 核心數。調整 GOMAXPROCS 參數可以影響調度行為,從而優化資源利用效率。

  8. 內存管理:Goroutine 的棧大小是動態調整的,從 2KB 開始,最大可達 1GB。這種動態調整機制使得 Goroutine 能夠更高效地利用內存資源,避免了固定大小棧帶來的浪費。

綜上所述,Goroutine 的調度策略在高并發場景下對系統資源的利用效率有顯著影響。通過合理的調度策略和優化方法,可以提高系統的性能和資源利用率。

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

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

相關文章

clickhouse-backup配置及使用(Linux)

一、下載地址 Releases Altinity/clickhouse-backup GitHub 二、上傳到服務器解壓安裝 自行上傳至服務器,解壓命令: tar xvf clickhouse-backup-linux-amd64.tar.gz 三、創建軟連接 sudo ln -sv build/linux/amd64/clickhouse-backup /usr/local/bin/…

如何在群暉NAS上安裝并配置MySQL與phpMyAdmin遠程管理數據庫

文章目錄 前言1. 安裝MySQL2. 安裝phpMyAdmin3. 修改User表4. 本地測試連接MySQL5. 安裝cpolar內網穿透6. 配置MySQL公網訪問地址7. 配置MySQL固定公網地址8. 配置phpMyAdmin公網地址9. 配置phpmyadmin固定公網地址 前言 大家是不是經常遇到需要隨時隨地訪問自己數據的情況&am…

《向量數據庫指南》——Milvus Cloud 2.5:Sparse-BM25引領全文檢索新時代

Milvus Cloud BM25:重塑全文檢索的未來 在最新的Milvus Cloud 2.5版本中,我們自豪地引入了“全新”的全文檢索能力,這一創新不僅鞏固了Milvus Cloud在向量數據庫領域的領先地位,更為用戶提供了前所未有的靈活性和效率。作為大禹智庫的向量數據庫高級研究員,以及《向量數據…

SQL 總結

SQL 總結 引言 SQL(Structured Query Language,結構化查詢語言)是一種用于管理關系數據庫管理系統(RDBMS)的標準編程語言。自1974年首次提出以來,SQL已成為數據庫領域中不可或缺的一部分。它允許用戶執行各種操作,如查詢、更新、插入和刪除數據庫中的數據。本文旨在提…

ESP32-CAM開發板入門 (下載示例程序)

ESP32-CAM開發板例程使用 1、準備工作1.1、硬件準備1.2、軟件準備 2、選擇示例程序并錄入第一步 1、準備工作 1.1、硬件準備 1.2、軟件準備 Arduino IDE : 編程與寫入(下載地址 https://www.arduino.cc/en/software) 安裝好后將軟件設置到…

企業賦能是什么意思-國際數字影像產業園解讀

在當今競爭激烈的商業環境中,企業賦能已成為推動企業發展、提升競爭力的關鍵策略。國際數字影像產業園作為數字影像產業的重要集聚地,通過一系列創新舉措為入駐園區的我眾多企業賦能。那么,企業賦能究竟是什么意思呢? 企業賦能是…

混合并行訓練框架性能對比

混合并行訓練框架性能對比 1. 框架類型 DeepSpeed、Megatron - LM、Colossal - AI、SageMaker、Merak、FasterMoE、Tutel、Whale、Alpa、DAPPLE、Mesh - TensorFlow 2. 可用并行性(Available parallelisms) DNN framework(深度神經網絡框架)DP(數據并行,Data Parallelis…

客戶案例:基于慧集通集成平臺,打通屠宰管理系統與用友U8C 系統的全攻略

一、引言 本原型客戶成立于2014年,是一家集飼草種植、肉牛養殖、精深加工、冷鏈物流、餐飲服務于一體的大型農牧綜合體。公司下設三個子公司分別涵蓋農業、畜牧業、肉制品加工業與餐飲物流服務業。公司嚴格按照一二三產業融合發展要求,以肉牛產業化為支…

HTML5滑塊(Slider)

HTML5 的滑塊&#xff08;Slider&#xff09;控件允許用戶通過拖動滑塊來選擇數值。以下是如何實現一個簡單的滑塊組件的詳細說明。 HTML5 滑塊組件 1. 基本結構 使用 <input type"range"> 元素可以創建一個滑塊。下面是基本實現的代碼示例&#xff1a; <…

25. C++繼承 1 (繼承的概念與基礎使用, 繼承的復制兼容規則,繼承的作用域)

?上篇模板文章&#xff1a;24. C模板 2 (非類型模板參數&#xff0c;模板的特化與模板的分離編譯)-CSDN博客 ?本篇代碼&#xff1a;c學習 橘子真甜/c-learning-of-yzc - 碼云 - 開源中國 (gitee.com) ?標?是比較重要的部分 目錄 一. 繼承的基礎使用 1.1 繼承的格式 1.2 …

露營小程序搭建有哪些步驟?小程序里面可以找個露營搭子

露營不僅僅是走進大自然的旅程&#xff0c;它也成為了一種社交和體驗式的活動。隨著小程序的普及&#xff0c;露營活動也越來越多地開始在線上開展。通過搭建一個露營小程序&#xff0c;商家不僅可以為用戶提供更多的露營選擇&#xff0c;還可以幫助他們找到合適的露營搭子。那…

XIAO ESP32 S3網絡攝像頭——2視頻獲取

本文主要是使用XIAO Esp32 S3制作網絡攝像頭的第2步,獲取攝像頭圖像。 1、效果如下: 2、所需硬件 3、代碼實現 3.1硬件代碼: #include "WiFi.h" #include "WiFiClient.h" #include "esp_camera.h" #include "camera_pins.h"// 設…

記一次 dockerfile 的循環依賴錯誤

文章目錄 1. 寫在最前面1.1 具體循環依賴的例子 2. 報錯的位置2.1 代碼快速分析2.2 代碼總結2.3 關于 parser 的記錄 3. 碎碎念 1. 寫在最前面 筆者在使用 dockerfile 多階段構建的功能時&#xff0c;寫出了一個「circular dependency detected on stage: xx」的錯誤。 解決方…

AAAI 2025論文分享┆一種接近全監督的無訓練文檔信息抽取方法:SAIL(文中附代碼鏈接)

本推文詳細介紹了一篇上海交通大學樂心怡老師課題組被人工智能頂級會議AAAI 2025錄用的的最新論文《SAIL: Sample-Centric In-Context Learning for Document Information Extraction》。論文的第一作者為張金鈺。該論文提出了一種無需訓練的、以樣本為中心的、基于上下文學習的…

小程序信息收集(小迪網絡安全筆記~

免責聲明&#xff1a;本文章僅用于交流學習&#xff0c;因文章內容而產生的任何違法&未授權行為&#xff0c;與文章作者無關&#xff01;&#xff01;&#xff01; 附&#xff1a;完整筆記目錄~ ps&#xff1a;本人小白&#xff0c;筆記均在個人理解基礎上整理&#xff0c;…

pat 乙級1096 大美數

若正整數 N 可以整除它的 4 個不同正因數之和&#xff0c;則稱這樣的正整數為“大美數”。本題就要求你判斷任一給定的正整數是否是“大美數”。 輸入格式&#xff1a; 輸入在第一行中給出正整數 K&#xff08;≤10&#xff09;&#xff0c;隨后一行給出 K 個待檢測的、不超過…

C#封送類

封送類&#xff08;Marshaling classes&#xff09;在.NET框架中扮演著至關重要的角色&#xff0c;尤其是在托管代碼與非托管代碼之間進行數據交換時。封送過程涉及到將托管環境中的對象轉換為非托管環境中可以理解的形式&#xff0c;并且反之亦然。這一過程確保了兩種不同類型…

計算機體系結構期末考試

1、描述計算機系統性能評估的關鍵指標&#xff0c;并以SPEC CPU benchmark為例&#xff0c;討論如何使用幾何平均數與加權平均數對性能進行量化。此外&#xff0c;描述Amdahl定律并分析該定律的應用場景及其對性能優化的局限性 2、請對比RISC和CISC指令集架構的設計思想及優缺點…

藥片缺陷檢測數據集,8625張圖片,使用YOLO,PASICAL VOC XML,COCO JSON格式標注,可識別藥品是否有缺陷,是否完整

藥片缺陷檢測數據集&#xff0c;8625張圖片&#xff0c;使用YOLO&#xff0c;PASICAL VOC XML&#xff0c;COCO JSON格式標注&#xff0c;可識別藥品是否有缺陷&#xff0c;是否完整 有缺陷的標注信息&#xff1a; 無缺陷的標注信息 數據集下載&#xff1a; yolov11:https://d…

一文講清楚CSS3新特性

文章目錄 一文講清楚CSS3新特性1. 新增選擇器特性2. 新增的樣式3. 新增布局方式 一文講清楚CSS3新特性 1. 新增選擇器特性 層次選擇器(div~p)選擇前面有div的p元素偽類選擇器 :first-of-type 表示?組同級元素中其類型的第?個元素:last-of-type 表示?組同級元素中其類型的最…