gpt4 book ai didi

go - WaitGroup 并发限制,但测试失败

转载 作者:行者123 更新时间:2023-12-01 22:21:03 24 4
gpt4 key购买 nike

我之前在goroutine中使用sync.WaitGroup,但是我想控制goroutine并发性,
所以我用并发限制写我的等待组:

package wglimit

import (
"sync"
)

// WaitGroupLimit ...
type WaitGroupLimit struct {
ch chan int
wg *sync.WaitGroup
}

// New ...
func New(size int) *WaitGroupLimit {
if size <= 0 {
size = 1
}
return &WaitGroupLimit{
ch: make(chan int, size), // buffer chan to limit concurrency
wg: &sync.WaitGroup{},
}
}

// Add ...
func (wgl *WaitGroupLimit) Add(delta int) {
for i := 0; i < delta; i++ {
wgl.ch <- 1
wgl.wg.Add(1)
}
}

// Done ...
func (wgl *WaitGroupLimit) Done() {
wgl.wg.Done()
<-wgl.ch
}

// Wait ...
func (wgl *WaitGroupLimit) Wait() {
close(wgl.ch)
wgl.wg.Wait()
}
然后,我用它来控制goroutine并发,例如:
jobs := ["1", "2", "3", "4"] // some jobs

// wg := sync.WaitGroup{} // have no concurrency limit
wg := wglimit.New(2) // limit 2 goroutine
for _, job := range jobs {
wg.Add(1)
go func(job string) {
// job worker
defer wg.Done()
}(job)
}
wg.Wait()
运行时看起来很正常。
但是测试失败:
package wglimit

import (
"runtime"
"testing"
"time"
)

func TestGoLimit(t *testing.T) {
var limit int = 5
wglimit := New(limit)
for i := 0; i < 10000; i++ {
wglimit.Add(1)
go func() {
defer wglimit.Done()
time.Sleep(time.Millisecond)
if runtime.NumGoroutine() > limit+2 {
println(runtime.NumGoroutine()) // will print 9 , cocurrent limit fail ?
t.Errorf("FAIL")
}
}()
}
wglimit.Wait()
}
测试时,goroutine数大于我的限制,似乎并发限制失败。
我的WaitGroupLimit代码有什么问题,为什么?

最佳答案

我的WaitGroupLimit代码[...]有什么问题吗?

没有。
问题是runtime.NumGoroutine()并没有执行您似乎认为的操作。它会计算所有goroutine,即不仅是您启动的goroutine,还包括运行时使用的goroutine,例如用于并发垃圾收集。因此,NumGoroutine高于您的限制。
您的代码很好,您的测试却没有。不要试图聪明地进行测试并测试代码的实际作用:在Add上它会阻塞,直到有限的资源可用为止。测试而不是goroutine计数,它只是测试中所需行为的(不良)代理。

关于go - WaitGroup 并发限制,但测试失败,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63554351/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com