1 回答

TA貢獻1798條經驗 獲得超7個贊
您的程序存在多個問題:
您正在生成多個對共享變量進行操作的goroutine,即,并導致數據競爭,因為它們不受保護(例如,受Mutex保護)。
max
num
這里由每個 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 關注
- 98 瀏覽
添加回答
舉報