並發程式設計技巧: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還提供了一些進階的用法,可以更靈活地控制並發任務的執行。以下我們將詳細介紹幾個常用的進階用法。
如果我們需要同時執行一組任務,但又希望限制最大並發數,可以使用帶緩衝通道結合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語句釋放令牌。透過控制令牌的獲取和釋放,我們就能夠限制最大並發數。
有時候我們希望對並發任務的執行時間進行控制,並在逾時時終止任務的執行。透過使用帶緩衝通道和定時器,我們可以輕鬆實現這個功能。下面的程式碼顯示如何設定並發任務的逾時時間為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中文網其他相關文章!