写了一段并发代码,初始化一个10w个元素的int数组,输出这10w个数之和,我的机器是2个cpu,每个cpu包含6个核,将数组分成12分子数组,分别用12个goroutine来算出子数组的和,最后求总和。
goroutine的执行单位是calsome()函数,我在这个函数的最后故意加了个死循环,结果执行时有时能安全退出(即输出result=4999950000),有时输出了若干个from=%d, subSum=%d就夯住了(此时通过top命令看到各个cpu核使用率都几乎达到100%),哪位大神能帮忙解释这种情况?
完整代码如下:
package main
import (
"fmt"
"runtime"
"time"
)
const COUNT int = 100000
const SIZE int = 100000
var MULTICORE int
func main() {
var num [SIZE]int
MULTICORE = runtime.NumCPU() //number of core
runtime.GOMAXPROCS(MULTICORE) //running in multicore
for i := 0; i < COUNT; i++ {
num[i] = i
}
fmt.Printf("result=%d\n", calmul(num[0:]))
}
func calmul(num []int) int {
t1 := time.Now()
ch := make(chan int)
fmt.Printf("with %d core\n", MULTICORE)
for i := 0; i < MULTICORE; i++ {
go calsome(i*COUNT/MULTICORE, (i+1)*COUNT/MULTICORE, num[0:], ch, i)
} //divide into some parts
result := 0;
for i := 0; i < MULTICORE; i++ {
temp := <-ch
result += temp
} //read result of some part from channel,loop will stop after all is read
t2 := time.Now()
fmt.Printf("multicore total time:%d\n", t2.Sub(t1))
return result
}
func calsome(from int, to int, num []int, ch chan int, i int) {
subSum := 0
for i := from; i < to; i++ {
subSum += num[i]
}
fmt.Printf("from=%d, subSum=%d\n", from,subSum);
ch <- subSum //put result in channel
j := 1;
**//这里做了死循环**
for j > 0{}
}
我 加上打印时间,反复验证了多次,这个问题会 偶尔出现。规律如下:除非全部gouroutine都进入 死循环,整体才会挂死;不信你可以在 make(chan ,MULTICORE) 变为非堵塞chan,则每次都会挂死,一定会挂死了。所以这个不是 golang 的 bug,而是每次都在不同调度。
#7
更多评论
问题应该是你的死循环问题上面.运行死循环占用大量cpu资源,这时候其他任务就不能正常执行,因此会出现程序"死亡"状态.该程序删掉j的死循环便可正常执行.
#1
有结果输出也是有可能的,ch <- subSum 是在死循环前,主goroutine是可以到,幸运的话还是输出结果的;要是有一个或者多个gorountine跑到了死循环, 这种空转cpu肯定回100%,还会导致其他goroutine没法执行
#2