首页 > 解决方案 > 如何保证一段代码执行不超过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 在块内。

提前致谢。

标签: gosynchronization

解决方案


这里的答案是信号量。这是一个片段:

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 实现了加权信号量


推荐阅读