首頁  >  文章  >  後端開發  >  並發程式設計技巧:Go WaitGroup的高階用法

並發程式設計技巧:Go WaitGroup的高階用法

王林
王林原創
2023-09-28 21:52:45886瀏覽

并发编程技巧:Go WaitGroup的高级用法

並發程式設計技巧:Go WaitGroup的高階用法

在並發程式設計中,協調和管理多個並發任務的執行是一項重要的任務。 Go語言提供了一個非常實用的並發原語——WaitGroup,它可以幫助我們優雅地實現並發控制。本文將介紹WaitGroup的基本用法,並重點討論其高級用法,透過具體的程式碼範例來幫助讀者更好地理解和應用。

WaitGroup是Go語言內建的一個並發原語,它能夠幫助我們等待並發任務的完成。它提供了三種方法:Add、Done和Wait。 Add方法用於設定等待任務的數量,Done方法用於減少等待任務的數量,Wait方法用於阻塞當前協程,直到所有等待任務完成。

下面是一個簡單的範例,展示了WaitGroup的基本用法:

package main

import (
    "fmt"
    "sync"
    "time"
)

func main() {
    var wg sync.WaitGroup

    for i := 0; i < 5; i++ {
        wg.Add(1)
        go func(num int) {
            defer wg.Done()

            time.Sleep(time.Second)
            fmt.Println("Task", num, "done")
        }(i)
    }

    wg.Wait()
    fmt.Println("All tasks done")
}

在上面的程式碼中,我們建立了一個WaitGroup物件wg,並透過循環創建了5個並發任務。在每個任務的執行過程中,我們使用Add方法增加等待任務的數量,並在任務結束時透過Done方法減少等待任務的數量。最後,我們呼叫Wait方法阻塞了主協程,直到所有等待任務完成。

除了基本的用法外,WaitGroup還提供了一些進階的用法,可以更靈活地控制並發任務的執行。以下我們將詳細介紹幾個常用的進階用法。

  1. 執行一組任務並設定最大並發數

如果我們需要同時執行一組任務,但又希望限制最大並發數,可以使用帶緩衝通道結合WaitGroup來實現。下面的程式碼展示瞭如何同時執行一組任務,但最多只允許3個任務並發執行:

package main

import (
    "fmt"
    "sync"
    "time"
)

func main() {
    var wg sync.WaitGroup
    maxConcurrency := 3
    tasks := []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}

    sem := make(chan struct{}, maxConcurrency)

    for _, task := range tasks {
        wg.Add(1)
        sem <- struct{}{} // 获取令牌,控制最大并发数

        go func(num int) {
            defer wg.Done()

            time.Sleep(time.Second)
            fmt.Println("Task", num, "done")

            <-sem // 释放令牌,允许新的任务执行
        }(task)
    }

    wg.Wait()
    fmt.Println("All tasks done")
}

在上面的程式碼中,我們創建了一個帶有緩衝的通道sem,並將其大小設置為最大並發數。在每個任務開始之前,我們透過sem <- struct{}{}語句取得一個令牌,當任務完成後,使用<-sem語句釋放令牌。透過控制令牌的獲取和釋放,我們就能夠限制最大並發數。

  1. 逾時控制並發任務的執行

有時候我們希望對並發任務的執行時間進行控制,並在逾時時終止任務的執行。透過使用帶緩衝通道和定時器,我們可以輕鬆實現這個功能。下面的程式碼顯示如何設定並發任務的逾時時間為3秒:

package main

import (
    "fmt"
    "sync"
    "time"
)

func main() {
    var wg sync.WaitGroup
    tasks := []int{1, 2, 3, 4, 5, 6, 7}

    timeout := 3 * time.Second
    done := make(chan struct{})

    for _, task := range tasks {
        wg.Add(1)

        go func(num int) {
            defer wg.Done()

            // 模拟任务执行时间不定
            time.Sleep(time.Duration(num) * time.Second)
            fmt.Println("Task", num, "done")

            // 判断任务是否超时
            select {
            case <-done:
                // 任务在超时前完成,正常退出
                return
            default:
                // 任务超时,向通道发送信号
                close(done)
            }
        }(task)
    }



    wg.Wait()
    fmt.Println("All tasks done")
}

在上面的程式碼中,我們建立了一個通道done,並在任務執行過程中判斷通道是否關閉來判斷任務是否超時。當一個任務完成時,我們使用close(done)語句向done通道發送訊號,表示任務已經逾時。透過select語句選擇不同的分支來處理不同的情況。

透過上面的範例程式碼,我們可以看到WaitGroup的高階用法在實際的並發程式設計中非常實用。掌握了這些技巧,我們能夠更好地控制並發任務的執行,提高程式碼的效能和可維護性。希望讀者能透過本文的介紹和範例程式碼,深入理解WaitGroup的用法,從而應用到實際的專案中。

以上是並發程式設計技巧:Go WaitGroup的高階用法的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn