首頁 > 後端開發 > Golang > Go併發解碼:Goroutine調度

Go併發解碼:Goroutine調度

Barbara Streisand
發布: 2025-01-14 22:08:45
原創
723 人瀏覽過

Go

我。 Goroutines:深入探討 Go 的並發模型

Goroutines 是 Go 設計的基石,為並發程式設計提供了強大的機制。 作為輕量級協程,它們簡化了並行任務執行。 啟動 goroutine 非常簡單:只需在函數呼叫前新增 go 關鍵字即可啟動非同步執行。主程式繼續執行,無需等待 goroutine 完成。

<code class="language-go">go func() { // Launch a goroutine using the 'go' keyword
    // ... code to be executed concurrently ...
}()</code>
登入後複製
登入後複製

二.了解 Goroutine 的內在機制

概念基礎

併發與並行

  • 並發: 在單一 CPU 上看似同時管理多個任務的能力。 CPU 在任務之間快速切換,產生並行執行的錯覺。 雖然微觀上是順序的,但宏觀上卻是並發的。

  • 並行性:跨多個CPU真正同時執行多個任務,消除CPU資源爭用。

行程與執行緒

  • 進程:有自己的資源(記憶體、檔案等)的獨立執行環境。 進程之間的切換是資源密集型的,需要核心級幹預。

  • 執行緒:進程內的輕量級執行單元,共享進程的資源。 執行緒切換比進程切換開銷更少。

協程

協程維護自己的暫存器上下文和堆疊。 協程之間的切換涉及保存和恢復此狀態,從而允許它們從中斷處恢復執行。 與進程和執行緒不同,協程管理是在使用者程式中處理的,而不是在作業系統中處理的。 Goroutines 是一種特定類型的協程。

GPM 調度模型

Go的高效並發依賴GPM調度模型。 涉及四個關鍵組件:M、P、G 和 Sched(Sched 未在圖中描繪)。

  • M(機器):核心級執行緒。 Goroutines 在 Ms.

    上運行
  • G(Goroutine): 單一 Goroutine。 每個 G 都有自己的堆疊、指令指標和其他與調度相關的資訊(例如,它正在等待的通道)。

  • P(處理器): 管理和執行 goroutine 的邏輯處理器。它維護一個就緒 goroutine 的運行隊列。

  • Sched(調度器):中央調度器,管理M和G隊列並確保高效的資源分配。

實際安排

Go

該圖顯示了兩個作業系統執行緒 (M),每個執行緒都有一個執行 goroutine 的處理器 (P)。

  • GOMAXPROCS() 控制 P 的數量(從而控制真正的並發等級)。

  • 灰色 G 已準備就緒,但尚未運作。 P 管理這個運行隊列。

  • 啟動一個 goroutine 將其加入到 P 的運行佇列中。

Go

如果 M0 被阻塞,P 會切換到 M1(可能會從執行緒快取中檢索)。

Go

如果一個 P 快速完成任務,它可能會竊取其他 P 的工作以保持效率。

三.使用 Goroutines

基本用法

設定goroutine執行的CPU數量(最近Go版本中的預設設定通常就足夠了):

<code class="language-go">go func() { // Launch a goroutine using the 'go' keyword
    // ... code to be executed concurrently ...
}()</code>
登入後複製
登入後複製

實際範例

範例1:簡單的Goroutine計算

<code class="language-go">num := runtime.NumCPU() // Get the number of logical CPUs
runtime.GOMAXPROCS(num) // Set the maximum number of concurrently running goroutines</code>
登入後複製

Goroutine 錯誤處理

goroutine 中未處理的異常可能會終止整個程式。在 recover() 語句中使用 defer 來處理恐慌:

<code class="language-go">package main

import (
    "fmt"
    "runtime"
)

func cal(a, b int) {
    c := a + b
    fmt.Printf("%d + %d = %d\n", a, b, c)
}

func main() {
    runtime.GOMAXPROCS(runtime.NumCPU())
    for i := 0; i < 10; i++ {
        go cal(i, i+1)
    }
    //Note:  The main function exits before goroutines complete in this example.  See later sections for synchronization.
}</code>
登入後複製

同步 Goroutines

由於 goroutine 非同步運行,主程式可能會在完成之前退出。 使用sync.WaitGroup或通道進行同步:

範例 1:使用 sync.WaitGroup

<code class="language-go">package main

import (
    "fmt"
)

func addele(a []int, i int) {
    defer func() {
        if r := recover(); r != nil {
            fmt.Println("Error in addele:", r)
        }
    }()
    a[i] = i // Potential out-of-bounds error if i is too large
    fmt.Println(a)
}

func main() {
    a := make([]int, 4)
    for i := 0; i < 5; i++ {
        go addele(a, i)
    }
    // ... (add synchronization to wait for goroutines to finish) ...
}</code>
登入後複製

範例2:使用通道進行同步

<code class="language-go">package main

import (
    "fmt"
    "sync"
)

func cal(a, b int, wg *sync.WaitGroup) {
    defer wg.Done()
    c := a + b
    fmt.Printf("%d + %d = %d\n", a, b, c)
}

func main() {
    var wg sync.WaitGroup
    for i := 0; i < 10; i++ {
        wg.Add(1)
        go cal(i, i+1, &wg)
    }
    wg.Wait()
}</code>
登入後複製

協程間通訊

通道促進了 goroutine 之間的通訊和資料共享。 也可以使用全域變量,但通常首選通道,以實現更好的並發控制。

範例:生產者-消費者模式

<code class="language-go">package main

import (
    "fmt"
)

func cal(a, b int, ch chan bool) {
    c := a + b
    fmt.Printf("%d + %d = %d\n", a, b, c)
    ch <- true // Signal completion
}

func main() {
    ch := make(chan bool, 10) // Buffered channel to avoid blocking
    for i := 0; i < 10; i++ {
        go cal(i, i+1, ch)
    }
    for i := 0; i < 10; i++ {
        <-ch // Wait for each goroutine to finish
    }
}</code>
登入後複製

Leapcell:Go 的無伺服器平台

Leapcell是部署Go服務的推薦平台。

Go

主要特點:

  1. 多語言支援: JavaScript、Python、Go、Rust。
  2. 免費無限制項目:即用即付定價。
  3. 性價比:無閒置費用。
  4. 開發人員友善:直覺的 UI、自動化 CI/CD、即時指標。
  5. 可擴展且高效能:自動擴展,零營運開銷。

Go

在文件中了解更多!

Leapcell Twitter:https://www.php.cn/link/7884effb9452a6d7a7a79499ef854afd

以上是Go併發解碼:Goroutine調度的詳細內容。更多資訊請關注PHP中文網其他相關文章!

來源:php.cn
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
作者最新文章
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板