自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

Golang 中的 WaitGroup 如何使用,面試官經(jīng)常考你

開發(fā) 開發(fā)工具
sync.WaitGroup?是 Go 語言標(biāo)準(zhǔn)庫中提供的一個(gè)并發(fā)控制工具,用于等待一組 goroutine 完成執(zhí)行。它本質(zhì)上是一個(gè)計(jì)數(shù)器,可以跟蹤正在運(yùn)行的 goroutine 數(shù)量。

什么是 WaitGroup

sync.WaitGroup 是 Go 語言標(biāo)準(zhǔn)庫中提供的一個(gè)并發(fā)控制工具,用于等待一組 goroutine 完成執(zhí)行。它本質(zhì)上是一個(gè)計(jì)數(shù)器,可以跟蹤正在運(yùn)行的 goroutine 數(shù)量。

WaitGroup 有三個(gè)主要方法:

Add(delta int)

 - 增加或減少等待的 goroutine 數(shù)量

Done()

 - 相當(dāng)于 Add(-1),表示一個(gè) goroutine 已完成

Wait()

 - 阻塞直到計(jì)數(shù)器歸零

基本用法

package main

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

func worker(id int, wg *sync.WaitGroup) {
defer wg.Done() // goroutine 完成時(shí)計(jì)數(shù)器減1

	fmt.Printf("Worker %d starting\n", id)
	time.Sleep(time.Second) // 模擬工作
	fmt.Printf("Worker %d done\n", id)
}

func main() {
var wg sync.WaitGroup

for i := 1; i <= 5; i++ {
		wg.Add(1) // 每啟動(dòng)一個(gè) goroutine 計(jì)數(shù)器加1
go worker(i, &wg)
}

	wg.Wait() // 等待所有 goroutine 完成
	fmt.Println("All workers completed")
}

WaitGroup 的常見誤用

1. 在 goroutine 內(nèi)部調(diào)用 Add

// 錯(cuò)誤用法
var wg sync.WaitGroup
for i := 0; i < 10; i++ {
go func() {
		wg.Add(1) // 可能在 Wait 之后才執(zhí)行
defer wg.Done()
// 工作代碼
}()
}
wg.Wait()

正確做法:在啟動(dòng) goroutine 前調(diào)用 Add

2. Add 和 Wait 的調(diào)用順序問題

// 錯(cuò)誤用法
var wg sync.WaitGroup
wg.Wait() // 可能直接通過,沒有等待
wg.Add(1)
go func() {
defer wg.Done()
// 工作代碼
}()

正確做法:確保所有 Add 調(diào)用在 Wait 之前完成

3. 傳遞 WaitGroup 值而非指針

// 錯(cuò)誤用法
func worker(wg sync.WaitGroup) {
defer wg.Done()
// 工作代碼
}

var wg sync.WaitGroup
wg.Add(1)
go worker(wg) // 值傳遞,Done 不影響原始 WaitGroup
wg.Wait()     // 永遠(yuǎn)等待

正確做法:傳遞 WaitGroup 指針

4. 計(jì)數(shù)器歸零后重用

var wg sync.WaitGroup
wg.Add(1)
go func() {
defer wg.Done()
}()
wg.Wait()

wg.Add(1) // 錯(cuò)誤: 在 Wait 之后再次使用

正確做法:WaitGroup 不能安全地重用,需要新建一個(gè)

WaitGroup + Channel 組合

結(jié)合 WaitGroup 和 Channel 可以實(shí)現(xiàn)更復(fù)雜的并發(fā)控制模式。

1. 限制并發(fā)數(shù)量

func main() {
var wg sync.WaitGroup
	ch := make(chan struct{}, 3) // 限制并發(fā)數(shù)為3

for i := 0; i < 10; i++ {
		wg.Add(1)
		ch <- struct{}{} // 獲取令牌

go func(i int) {
defer wg.Done()
defer func() { <-ch }() // 釋放令牌

			fmt.Printf("Worker %d starting\n", i)
			time.Sleep(time.Second)
			fmt.Printf("Worker %d done\n", i)
}(i)
}

	wg.Wait()
}

2. 收集 goroutine 結(jié)果

func worker(id int, wg *sync.WaitGroup, resChan chan<- string) {
defer wg.Done()

// 模擬工作
	time.Sleep(time.Second)
	resChan <- fmt.Sprintf("result from worker %d", id)
}

func main() {
var wg sync.WaitGroup
	resChan := make(chan string, 10)

// 啟動(dòng)多個(gè) worker
for i := 0; i < 5; i++ {
		wg.Add(1)
go worker(i, &wg, resChan)
}

// 等待所有 worker 完成
go func() {
		wg.Wait()
close(resChan) // 所有結(jié)果收集完畢后關(guān)閉 channel
}()

// 處理結(jié)果
for res := range resChan {
		fmt.Println(res)
}
}

高級(jí)用法:動(dòng)態(tài)調(diào)整并發(fā)數(shù)

func dynamicWorker(id int, wg *sync.WaitGroup, sem chan struct{}) {
defer wg.Done()

	fmt.Printf("Worker %d started\n", id)
	time.Sleep(time.Second * 2)
	fmt.Printf("Worker %d finished\n", id)

<-sem // 釋放信號(hào)量
}

func main() {
var wg sync.WaitGroup
	maxConcurrent := 3
	sem := make(chan struct{}, maxConcurrent)

for i := 0; i < 10; i++ {
		sem <- struct{}{} // 獲取信號(hào)量
		wg.Add(1)
go dynamicWorker(i, &wg, sem)
}

	wg.Wait()
	fmt.Println("All workers completed")
}

總結(jié)

WaitGroup 是 Go 中管理 goroutine 生命周期的強(qiáng)大工具,但需要注意:

  • 總是使用指針傳遞 WaitGroup
  • 在啟動(dòng) goroutine 前調(diào)用 Add
  • 不要重用 WaitGroup
  • 結(jié)合 Channel 可以實(shí)現(xiàn)更精細(xì)的并發(fā)控制

通過合理使用 WaitGroup 和 Channel 的組合,可以構(gòu)建出高效且安全的并發(fā)程序。

責(zé)任編輯:武曉燕 來源: Go語言圈
相關(guān)推薦

2015-08-13 10:29:12

面試面試官

2024-09-14 10:50:29

通信代碼函數(shù)

2010-08-12 16:28:35

面試官

2021-05-19 06:07:21

CSS 斜線效果技巧

2023-02-16 08:10:40

死鎖線程

2024-10-15 10:00:06

2023-06-05 09:23:00

Golang同步工具

2021-07-06 07:08:18

管控數(shù)據(jù)數(shù)倉

2024-09-11 22:51:19

線程通訊Object

2024-04-03 00:00:00

Redis集群代碼

2025-03-17 00:00:00

2023-11-20 10:09:59

2024-03-18 14:06:00

停機(jī)Spring服務(wù)器

2024-02-20 14:10:55

系統(tǒng)緩存冗余

2020-08-06 07:49:57

List元素集合

2024-12-25 15:44:15

2015-08-24 09:00:36

面試面試官

2024-02-04 10:08:34

2020-09-30 06:49:25

MySQL查詢刪除

2022-05-23 08:43:02

BigIntJavaScript內(nèi)置對(duì)象
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)