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

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

Sep 28, 2023 pm 09:52 PM
go 並發程式設計 waitgroup

并发编程技巧: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

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)

C++ 並發程式設計中資料結構的同時安全設計? C++ 並發程式設計中資料結構的同時安全設計? Jun 05, 2024 am 11:00 AM

在C++並發程式設計中,資料結構的並發安全設計至關重要:臨界區:使用互斥鎖建立程式碼區塊,僅允許一個執行緒同時執行。讀寫鎖:允許多個執行緒同時讀取,但只有一個執行緒同時寫入。無鎖資料結構:使用原子操作實現並發安全,無需鎖。實戰案例:執行緒安全的佇列:使用臨界區保護佇列操作,實現執行緒安全性。

Go WebSocket 訊息如何發送? Go WebSocket 訊息如何發送? Jun 03, 2024 pm 04:53 PM

在Go中,可以使用gorilla/websocket包發送WebSocket訊息。具體步驟:建立WebSocket連線。傳送文字訊息:呼叫WriteMessage(websocket.TextMessage,[]byte("訊息"))。發送二進位訊息:呼叫WriteMessage(websocket.BinaryMessage,[]byte{1,2,3})。

Golang 與 Go 語言的區別 Golang 與 Go 語言的區別 May 31, 2024 pm 08:10 PM

Go和Go語言是不同的實體,具有不同的特性。 Go(又稱Golang)以其並發性、編譯速度快、記憶體管理和跨平台優點而聞名。 Go語言的缺點包括生態系統不如其他語言豐富、文法更嚴格、缺乏動態類型。

如何在 Go 中使用正規表示式匹配時間戳記? 如何在 Go 中使用正規表示式匹配時間戳記? Jun 02, 2024 am 09:00 AM

在Go中,可以使用正規表示式比對時間戳記:編譯正規表示式字串,例如用於匹配ISO8601時間戳記的表達式:^\d{4}-\d{2}-\d{2}T \d{2}:\d{2}:\d{2}(\.\d+)?(Z|[+-][0-9]{2}:[0-9]{2})$ 。使用regexp.MatchString函數檢查字串是否與正規表示式相符。

C++ 並發程式設計中的同步原語詳解 C++ 並發程式設計中的同步原語詳解 May 31, 2024 pm 10:01 PM

在C++多執行緒程式設計中,同步原語的作用是保證多個執行緒存取共享資源時的正確性,它包括:互斥鎖(Mutex):保護共享資源,防止同時存取;條件變數(ConditionVariable):執行緒等待特定條件滿足才繼續執行;原子操作:保證操作以不可中斷的方式執行。

Golang 技術效能優化中如何避免記憶體洩漏? Golang 技術效能優化中如何避免記憶體洩漏? Jun 04, 2024 pm 12:27 PM

記憶體洩漏會導致Go程式記憶體不斷增加,可通過:關閉不再使用的資源,如檔案、網路連線和資料庫連線。使用弱引用防止記憶體洩漏,當物件不再被強引用時將其作為垃圾回收目標。利用go協程,協程棧記憶體會在退出時自動釋放,避免記憶體洩漏。

Golang 函數接收 map 參數時的注意事項 Golang 函數接收 map 參數時的注意事項 Jun 04, 2024 am 10:31 AM

在Go中傳遞map給函數時,預設會建立副本,對副本的修改不影響原map。如果需要修改原始map,可透過指標傳遞。空map需小心處理,因為技術上是nil指針,傳遞空map給期望非空map的函數會發生錯誤。

如何使用 Golang 的錯誤包裝器? 如何使用 Golang 的錯誤包裝器? Jun 03, 2024 pm 04:08 PM

在Golang中,錯誤包裝器允許你在原始錯誤上追加上下文訊息,從而創建新錯誤。這可用於統一不同程式庫或元件拋出的錯誤類型,簡化偵錯和錯誤處理。步驟如下:使用errors.Wrap函數將原有錯誤包裝成新錯誤。新錯誤包含原始錯誤的上下文資訊。使用fmt.Printf輸出包裝後的錯誤,提供更多上下文和可操作性。在處理不同類型的錯誤時,使用errors.Wrap函數統一錯誤類型。

See all articles