关于goroutine的问题,求质数的案例

weixin_38065223 2019-09-20 10:44:41
```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?求大佬们解答一下,小弟感激不尽。
...全文
45 4 打赏 收藏 转发到动态 举报
写回复
用AI写文章
4 条回复
切换为时间正序
请发表友善的回复…
发表回复
weixin_38117299 2019-09-20
  • 打赏
  • 举报
回复
如果去掉 go func,在所有执行完之前,最后的 `v, ok := <- resChan` 没机会执行到
weixin_38119848 2019-09-20
  • 打赏
  • 举报
回复
感谢回答,但是还是没太懂,要的效果就是让所有的`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。
weixin_38123446 2019-09-20
  • 打赏
  • 举报
回复
哦!!明白了,因为`resChan`的缓冲容量太少了,每个goroutine写满了`resChan`,要等待`<-resChan`,但是main goroutine的取出`resChan`没有机会执行,所以死锁了.
weixin_38125855 2019-09-20
  • 打赏
  • 举报
回复
没说根源吧。go func 是另起一个协程执行那一段匿名函数,而直接写for 是顺序执行,所以卡住了

433

社区成员

发帖
与我相关
我的任务
社区描述
其他技术讨论专区
其他 技术论坛(原bbs)
社区管理员
  • 其他技术讨论专区社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧