写了一段并发代码,初始化一个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{}
}
对于能正常输出的情况,我的理解是这样的:12个gorountine被分到了不同的核上,几乎同时到达ch <- subSum后,calmul()被唤醒输出,此时貌似gorountine无论走到死循环与否,都能安全退出。
不正常的情况比较困惑:假如12个gorountine中的几个被分到同一个核,那么一个gorountine进入死循环后势必会堵塞同一个核上的其他gorountine,这样应该只影响某个核,但为何会引发所有cpu核都到100%?
#5
更多评论
问题应该是你的死循环问题上面.运行死循环占用大量cpu资源,这时候其他任务就不能正常执行,因此会出现程序"死亡"状态.该程序删掉j的死循环便可正常执行.
#1
有结果输出也是有可能的,ch <- subSum 是在死循环前,主goroutine是可以到,幸运的话还是输出结果的;要是有一个或者多个gorountine跑到了死循环, 这种空转cpu肯定回100%,还会导致其他goroutine没法执行
#2