go - 如何保证一段代码执行不超过n次
问题描述
我想为 goroutine 中的一段代码设置并发限制。
我查看了mutex
, 频道,但无法做到这一点。
m.Lock()
// make request to server
log.Info("Calling server for " + name)
resp, err := netClient.Do(req)
m.Unlock()
log.Info("outside lock for " + name)
使用上面的代码片段,我可以一个接一个地限制服务器调用。相反,有没有一种方法可以让 4 个 goroutine 执行这个调用。只有在这 4 个中的任何一个响应后,另一个 goroutine 才能执行它。所以我一次需要 4 个 goroutine 在块内。
提前致谢。
解决方案
这里的答案是信号量。这是一个片段:
package main
import (
"fmt"
"sync"
)
func main() {
numOfGoroutines := 4
sem := make(chan struct{}, numOfGoroutines)
wg := sync.WaitGroup{}
for i := 0; i < 100; i++ {
sem <- struct{}{}
wg.Add(1)
go func(i int) {
defer func() { <-sem }()
defer wg.Done()
fmt.Println(i)
}(i)
}
wg.Wait()
fmt.Println("done")
}
这个片段有一个重要的细节,彼得提到的链接中缺少这个细节。该片段在继续之前等待所有 goroutine 完成。
此外,Go 实现了加权信号量。