1 回答

TA貢獻(xiàn)1798條經(jīng)驗(yàn) 獲得超7個(gè)贊
您的程序存在多個(gè)問題:
您正在生成多個(gè)對(duì)共享變量進(jìn)行操作的goroutine,即,并導(dǎo)致數(shù)據(jù)競(jìng)爭(zhēng),因?yàn)樗鼈儾皇鼙Wo(hù)(例如,受Mutex保護(hù))。
max
num
這里由每個(gè) worker goroutine 修改,但它應(yīng)該是 worker 的本地,否則計(jì)算的數(shù)據(jù)可能會(huì)丟失(例如,一個(gè) worker goroutine 計(jì)算了一個(gè)結(jié)果并將其存儲(chǔ)在 num 中,但緊隨其后,第二個(gè) worker 計(jì)算并替換了 num 的值)。
num
num = compute // Should be "num := compute"
您不會(huì)等待每個(gè) goroutine 完成計(jì)算,這可能會(huì)導(dǎo)致不正確的結(jié)果,因?yàn)榧词股舷挛奈慈∠?,也不?huì)考慮每個(gè)工作線程計(jì)算。使用 或 渠道來解決此問題。
sync.WaitGroup
下面是一個(gè)示例程序,可解決代碼中的大多數(shù)問題:
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在注釋中指出的那樣,當(dāng)上下文被取消時(shí),請(qǐng)確保停止那些工作線程goroutines以停止處理(如果可能的話),因?yàn)樗辉傩枰恕?/p>
- 1 回答
- 0 關(guān)注
- 94 瀏覽
添加回答
舉報(bào)