```go
func PrimeNum(start, end int, resChan chan int, exitChan chan bool) {
var i, j int
var flag bool
for i = start; i < end; i++ {
if i == 0 || i == 1 {
continue
}
flag = true
k := int(math.Sqrt(float64(i)))
for j = 2; j <= k; j++ {
if i%j == 0 {
flag = false
break
}
}
if flag {
resChan <- i
}
}
exitChan <- true
}
func main() {
res := make([]int, 0) // 存储质数的切片
end := 100000 // 100000范围内的质数
step := 20000 // 分配每个goroutine20000个数来求质数
times := end / step
routineCount := times // 需要多少个gouroutine
if end%step != 0 {
routineCount++
}
var resChan = make(chan int, 50) // 临时存储质数的chan
var exitChan = make(chan bool, routineCount) // 记录goroutine退出
var i int
for i = 0; i < times; i++ {
go PrimeNum(i*step, (i+1)*step, resChan, exitChan)
}
if routineCount > times {
go PrimeNum(i*step, end+1, resChan, exitChan)
}
// 为什么不能直接for而需要一个goroutine?
go func() {
for i = 0; i < routineCount; i++ {
<-exitChan
}
close(resChan) // 关闭resChan
}()
for {
v, ok := <-resChan
if !ok {
break
}
res = append(res, v) // 写入切片
}
fmt.Println(len(res))
}
```
在`main()`里面取`exitChan`的时候为什么需要一个go func? 我试过去掉那个go func,程序会deadlock,为什么?exitChan是有写入和取出的。还是说在main主线程中直接取exitChan时因为没有数据而造成主线程阻塞从而引发panic?求大佬们解答一下,小弟感激不尽。
感谢回答,但是还是没太懂,要的效果就是让所有的`PrimeNum`执行完毕后(`exitChan写满`)然后再从`resChan`中取出结果数据。类似的思路是这样:
```go
func main() {
var exitChan = make(chan bool, 4)
var resChan = make(chan int, 4)
for i := 0; i < 4; i++ {
go func(n int) {
resChan <- n
exitChan <- true
}(i)
}
for i := 0; i < 4; i++ {
fmt.Println(<-exitChan) // 等待4个goroutine退出
}
close(resChan)
for {
// 读取resChan的数据
if res, ok := <-resChan; !ok {
break
} else {
fmt.Println("res:", res)
}
}
}
```
这和那个求质数的思路是一样的,但是这样就不会报deadlock。
#2
更多评论
哦!!明白了,因为`resChan`的缓冲容量太少了,每个goroutine写满了`resChan`,要等待`<-resChan`,但是main goroutine的取出`resChan`没有机会执行,所以死锁了.
#3