并发执行的协程太多可能会对系统资源的消耗特别大,从而导致其它进程服务受到影响,因此协程执行时应该设计一种机制,来限制并发执行的协程数目。
其中 WaitGroup 主要用作协程同步,当所有协程都执行完毕以后,才会结束主线程。每个任务开始执行前,都会先往缓冲通道写入空结构体数据(用于占位),如果通道已满,则会阻塞,直到通道数据被其他协程取出释放后当前协程才可以继续执行。
package mainimport ("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 := 3sem := make(chan struct{}, concurrency)var wg sync.WaitGroupfor 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