1 回答
TA贡献1798条经验 获得超7个赞
您的程序存在多个问题:
您正在生成多个对共享变量进行操作的goroutine,即,并导致数据竞争,因为它们不受保护(例如,受Mutex保护)。
maxnum这里由每个 worker goroutine 修改,但它应该是 worker 的本地,否则计算的数据可能会丢失(例如,一个 worker goroutine 计算了一个结果并将其存储在 num 中,但紧随其后,第二个 worker 计算并替换了 num 的值)。
num
num = compute // Should be "num := compute"
您不会等待每个 goroutine 完成计算,这可能会导致不正确的结果,因为即使上下文未取消,也不会考虑每个工作线程计算。使用 或 渠道来解决此问题。
sync.WaitGroup
下面是一个示例程序,可解决代码中的大多数问题:
package main
import (
"context"
"fmt"
"math/rand"
"sync"
"time"
)
type result struct {
sync.RWMutex
max uint64
}
func findMax(ctx context.Context, workers int) uint64 {
var (
res = result{}
wg = sync.WaitGroup{}
)
for i := 0; i < workers; i++ {
select {
case <-ctx.Done():
// RLock to read res.max
res.RLock()
ret := res.max
res.RUnlock()
return ret
default:
wg.Add(1)
go func() {
defer wg.Done()
num := compute()
// Lock so that read from res.max and write
// to res.max is safe. Else, data race could
// occur.
res.Lock()
if num > res.max {
res.max = num
}
res.Unlock()
}()
}
}
// Wait for all the goroutine to finish work i.e., all
// workers are done computing and updating the max.
wg.Wait()
return res.max
}
func compute() uint64 {
rnd := rand.Int63n(100)
time.Sleep(time.Duration(rnd) * time.Millisecond)
return rand.Uint64()
}
func main() {
maxDuration := 2 * time.Second
concurrency := 10
ctx, cancel := context.WithTimeout(context.Background(), maxDuration)
defer cancel()
fmt.Println(findMax(ctx, concurrency))
}
正如@Brits在注释中指出的那样,当上下文被取消时,请确保停止那些工作线程goroutines以停止处理(如果可能的话),因为它不再需要了。
- 1 回答
- 0 关注
- 120 浏览
添加回答
举报
