sync.WaitGroup
和信号量是Golang和并发编程中常用的概念,帮助我们管理和控制并发任务的执行顺序、数量以及同步。
1. sync.WaitGroup
简介
sync.WaitGroup
是Golang标准库中的一个同步原语,用于等待一组协程(goroutine)完成工作。在多个并发任务执行时,它可以帮助主协程等待所有任务完成再继续执行或退出。
使用方法
sync.WaitGroup
的工作原理是计数:
- 增加计数:通过调用
Add(n)
增加计数,表示将要执行n
个任务。 - 减少计数:每当一个任务完成时,调用
Done()
减少计数。 - 等待完成:调用
Wait()
阻塞等待,直到计数归零,表示所有任务已完成。
示例
假设我们要启动3个并发任务,并等待它们都完成:
package main import ( "fmt" "sync" ) func main() { var wg sync.WaitGroup // 启动3个协程 for i := 1; i <= 3; i++ { wg.Add(1) // 增加计数 go func(i int) { defer wg.Done() // 减少计数 fmt.Printf("Task %d is done\n", i) }(i) } // 等待所有任务完成 wg.Wait() fmt.Println("All tasks completed.") }在这个例子中,
wg.Add(1)
增加计数,wg.Done()
减少计数,而wg.Wait()
会阻塞,直到所有任务完成后解除阻塞并继续执行。
2. 信号量(Semaphore)
信号量是一种用于控制资源访问的并发机制。通过信号量可以限制并发任务的最大数量(即资源的使用量),在实际应用中,例如限制并发处理的协程数量。
在Golang中,可以用带缓冲的通道(chan struct{}
)来实现一个简单的信号量。
实现信号量的关键原理
- 缓冲通道的容量:将通道的缓冲容量设置为允许的最大并发数量(例如,3)。
- 获取信号量:每个任务开始时向通道发送一个信号(
sem <- struct{}{}
),表示该资源正在被占用。 - 释放信号量:任务完成后从通道读取一个信号(
<-sem
),表示资源已释放。
示例
假设我们想同时只允许3个协程运行,超出的任务需要等待:
package main import ( "fmt" "time" ) func main() { // 创建容量为3的信号量通道 sem := make(chan struct{}, 3) for i := 1; i <= 5; i++ { // 获取信号量 sem <- struct{}{} go func(i int) { defer func() { <-sem }() // 释放信号量 fmt.Printf("Task %d is starting\n", i) time.Sleep(2 * time.Second) // 模拟任务耗时 fmt.Printf("Task %d is done\n", i) }(i) } // 等待所有任务完成 time.Sleep(6 * time.Second) fmt.Println("All tasks completed.") }
------console.log----- Task 3 is starting Task 1 is starting Task 2 is starting Task 1 is done Task 3 is done Task 2 is done Task 4 is starting Task 5 is starting Task 5 is done Task 4 is done All tasks completed.
在这个例子中,最多只允许3个任务同时运行。当任务完成后,它们会从信号量通道中释放一个信号,让其他等待中的任务可以启动。
sync.WaitGroup
和信号量(Semaphore)都是用于并发处理的机制
但它们解决的问题和适用的场景略有不同:
sync.WaitGroup
:是一种同步机制,用于等待一组并发任务完成,适合用来控制并发任务的生命周期。WaitGroup
的作用是确保多个协程(goroutine)都执行完成后,再继续执行后续的逻辑,但它并不限制并发任务的数量。适用场景:需要等待一组并发任务完成才能进行下一步时使用。例如在主协程中等待所有子协程的任务完成后再退出。
核心操作:
- 增加计数
Add(n)
- 减少计数
Done()
- 等待计数归零
Wait()
- 增加计数
信号量(Semaphore):是一种并发控制机制,用于限制同时运行的并发任务数量。在Golang中,通过带缓冲的通道来实现信号量,控制并发资源的访问。
适用场景:限制并发数量,确保同时运行的任务不会超过某个上限。例如,限制最大并发处理数量为3的场景。
核心操作:
- 获取信号量:向缓冲通道发送信号(表示资源被占用)
- 释放信号量:从缓冲通道读取信号(表示资源被释放)
总结
sync.WaitGroup
:管理并发任务完成的同步,不限制数量。- 信号量:控制并发任务的数量,限制资源使用。
两者结合使用时可以既控制任务并发数(信号量),又确保所有任务完成后再继续(WaitGroup
)。
没有评论:
发表评论