面试题答案
一键面试生成器与sync包原语协作的典型应用场景
- 资源共享与竞争控制:当多个协程需要访问共享资源(如数据库连接池、缓存等)时,可能会出现资源竞争问题。生成器可以产生对这些共享资源的操作请求,而
Mutex
可以用来保护共享资源,确保同一时间只有一个协程能访问它。 - 协程同步:在一些场景下,需要等待一组协程全部完成任务后再进行下一步操作。例如,一个生成器生成任务,多个协程并行处理这些任务,
WaitGroup
可以用来同步这些协程,确保所有任务都完成后程序继续执行。
使用示例
- 使用Mutex解决资源竞争问题
package main
import (
"fmt"
"sync"
)
// 假设这是一个共享资源
var sharedResource int
var mu sync.Mutex
// 生成器函数,生成操作共享资源的任务
func generator(wg *sync.WaitGroup) {
for i := 0; i < 10; i++ {
go func(id int) {
defer wg.Done()
// 加锁保护共享资源
mu.Lock()
sharedResource += id
fmt.Printf("协程 %d 修改共享资源为 %d\n", id, sharedResource)
mu.Unlock()
}(i)
}
}
func main() {
var wg sync.WaitGroup
wg.Add(10)
generator(&wg)
wg.Wait()
fmt.Printf("最终共享资源的值为: %d\n", sharedResource)
}
在上述代码中,generator
函数创建多个协程对共享资源sharedResource
进行操作。Mutex
的Lock
和Unlock
方法确保同一时间只有一个协程能够修改sharedResource
,从而避免资源竞争。
- 使用WaitGroup进行协程同步
package main
import (
"fmt"
"sync"
)
// 生成器函数,生成需要处理的任务
func generator(wg *sync.WaitGroup) <-chan int {
resultChan := make(chan int)
go func() {
for i := 0; i < 5; i++ {
wg.Add(1)
go func(id int) {
defer wg.Done()
result := id * id
resultChan <- result
}(i)
}
close(resultChan)
}()
return resultChan
}
func main() {
var wg sync.WaitGroup
resultChan := generator(&wg)
go func() {
wg.Wait()
close(resultChan)
}()
for result := range resultChan {
fmt.Printf("收到结果: %d\n", result)
}
}
在这个示例中,generator
函数创建多个协程处理任务,并使用WaitGroup
来同步这些协程。主协程通过for... range
从通道resultChan
中接收处理结果,确保在所有协程完成任务后才结束程序。