并发执行的协程太多可能会对系统资源的消耗特别大,从而导致其它进程服务受到影响,因此协程执行时应该设计一种机制,来限制并发执行的协程数目。
其中 WaitGroup 主要用作协程同步,当所有协程都执行完毕以后,才会结束主线程。每个任务开始执行前,都会先往缓冲通道写入空结构体数据(用于占位),如果通道已满,则会阻塞,直到通道数据被其他协程取出释放后当前协程才可以继续执行。
package main
import (
"fmt"
"sync"
"time"
)
func worker(id int, sem chan struct{}) {
sem <- struct{}{}
defer func() {
<-sem
}()
fmt.Printf("%s: Worker %d starting...\n", time.Now().Format("2006-01-02 15:04:05"), id)
time.Sleep(2 * time.Second)
fmt.Printf("Worker %d done\n", id)
}
func main() {
concurrency := 3
sem := make(chan struct{}, concurrency)
var wg sync.WaitGroup
for i := 0; i < 10; i++ {
wg.Add(1)
go func(id int) {
defer wg.Done()
worker(id, sem)
}(i)
}
wg.Wait()
close(sem)
}
2024-04-09 09:27:25: Worker 1 starting...
2024-04-09 09:27:25: Worker 3 starting...
2024-04-09 09:27:25: Worker 0 starting...
Worker 3 done
Worker 0 done
2024-04-09 09:27:27: Worker 4 starting...
2024-04-09 09:27:27: Worker 2 starting...
Worker 1 done
2024-04-09 09:27:27: Worker 5 starting...
Worker 5 done
2024-04-09 09:27:29: Worker 6 starting...
Worker 4 done
2024-04-09 09:27:29: Worker 9 starting...
Worker 2 done
2024-04-09 09:27:29: Worker 8 starting...
Worker 6 done
Worker 9 done
Worker 8 done
2024-04-09 09:27:31: Worker 7 starting...
Worker 7 done