1 回答

TA貢獻(xiàn)1816條經(jīng)驗(yàn) 獲得超4個(gè)贊
看起來您同時(shí)運(yùn)行了太多東西,導(dǎo)致您的計(jì)算機(jī)內(nèi)存不足。
這是您的代碼版本,它使用有限數(shù)量的工作程序 goroutines 而不是您的示例中的一百萬個(gè) goroutines。由于一次只有幾個(gè) goroutine 運(yùn)行,因此在系統(tǒng)開始交換之前,它們每個(gè)都有更多的可用內(nèi)存。確保每個(gè)小計(jì)算所需的內(nèi)存乘以并發(fā) goroutines 的數(shù)量小于您系統(tǒng)中的內(nèi)存,因此如果for jdId := range work循環(huán)內(nèi)的代碼需要少于 1GB 的內(nèi)存,并且您有 4 個(gè)內(nèi)核和至少 4 GB 的 RAM,設(shè)置clvl為4應(yīng)該可以正常工作。
我還刪除了等待組。代碼仍然是正確的,但僅使用通道進(jìn)行同步。通道上的 for 范圍循環(huán)從該通道讀取,直到它關(guān)閉。這就是我們在完成時(shí)告訴工作線程的方式。
https://play.golang.org/p/Sy3i77TJjA
runtime.GOMAXPROCS(runtime.NumCPU()) // not needed on go 1.5 or later
c := make(chan string)
work := make(chan int, 1) // increasing 1 to a higher number will probably increase performance
clvl := 4 // runtime.NumCPU() // simulating having 4 cores, use NumCPU otherwise
var wg sync.WaitGroup
wg.Add(clvl)
for i := 0; i < clvl; i++ {
go func(i int) {
for jdId := range work {
time.Sleep(time.Millisecond * 100)
c <- fmt.Sprintf("done %d", jdId)
}
wg.Done()
}(i)
}
// give workers something to do
go func() {
for i := 0; i < 10; i++ {
work <- i
}
close(work)
}()
// close output channel when all workers are done
go func() {
wg.Wait()
close(c)
}()
count := 0
for resp := range c {
fmt.Println(resp, count)
count += 1
}
它在 go playground 上生成了這個(gè)輸出,同時(shí)模擬了四個(gè) CPU 內(nèi)核。
done 1 0
done 0 1
done 3 2
done 2 3
done 5 4
done 4 5
done 7 6
done 6 7
done 9 8
done 8 9
請注意如何不保證排序。該jdId變量保存您想要的值。您應(yīng)該始終使用gorace 檢測器來測試您的并發(fā)程序。
另請注意,如果您使用的是 go 1.4 或更早版本并且尚未將 GOMAXPROCS 環(huán)境變量設(shè)置為內(nèi)核數(shù),則應(yīng)該這樣做,或者添加runtime.GOMAXPROCS(runtime.NumCPU())到程序的開頭。
- 1 回答
- 0 關(guān)注
- 289 瀏覽
添加回答
舉報(bào)