【初学Go】请教关于并发的问题

myGoStudy · 2024-09-26 16:53:59 · 994 次点击 · 大约8小时之前 开始浏览    置顶
这是一个创建于 2024-09-26 16:53:59 的主题,其中的信息可能已经有所发展或是发生改变。

刚学习到并发,写了一个关于判断某些范围内有哪些素数,但是运行时发现了问题,百思不得其解。请大佬解惑!

修改后的代码是可以把范围内的所有素数正常打印出来,\n但有问题的代码却只能打印前几个,worker创建的多则打印的结果就多。

两段代码唯一不同的地方就是将原来判断是否为素数的功能单独写成了一个函数:这个功能写在worker里就不正常,独立成函数就正常输出。想不明白为什么会这样?

这是有问题的代码:

package main

import (
    "fmt"
    "sync"
    "time"
)

//存放结果
var rltChan = make(chan int, 10)
//存放工作内容
var jobsChan = make(chan int , 10)

//判断是否为素数
func worker(wg *sync.WaitGroup)  {
    defer wg.Done()
    for job := range jobsChan {
        if job%2==0 {
            return
        }else{
            for i := 3; i < job; i+=2 {
                if job%i == 0 {
                    return
                }
            }

            rltChan <- job
        }
    }

}

//创建工作池
func createWorkerPool(numOfWorker int)  {
    var wg sync.WaitGroup
    for i := 0; i < numOfWorker; i++ {
        wg.Add(1)
        go worker(&wg)
    }
    wg.Wait()
    close(rltChan)
}

//将1至numOfJobs以内的整数依次写入jobsChan中
func allocate(numOfJobs int)  {
    for i := 1; i < numOfJobs; i++ {
        jobsChan <- i
    }
    close(jobsChan)
}

//显示所有的结果
func display(disChan chan bool)  {
    for result := range rltChan {
        fmt.Println(result)
    }
    disChan <- true
}

func main(){
    start := time.Now()
    //寻找素数的范围
    number := 2000
    //规定worker的个数
    numOfWorker := 10
    //确保输出显示全部完成
    disChan := make(chan bool)

    go allocate(number)

    go display(disChan)

    createWorkerPool(numOfWorker)

    //全部显示完毕
    <- disChan
    end := time.Now()
    diff := end.Sub(start)
    fmt.Println("耗费时间:",diff.Seconds())
}

这是修改后正常的代码

package main

import (
    "fmt"
    "sync"
    "time"
)

//存放结果
var rltChan = make(chan int, 10)
//存放工作内容
var jobsChan = make(chan int , 10)

//判断是否为素数
func isSuShu(num int) (int, bool) {
    if num%2==0 {
        return num, false
    }else{
        for i := 3; i < num; i+=2 {
            if num%i == 0 {
                return num, false
            }
        }
        return num, true
    }
}

func worker(wg *sync.WaitGroup)  {
    defer wg.Done()
    for job := range jobsChan {
        if num, ok := isSuShu(job);ok{
            rltChan <- num
        }
    }

}

//创建工作池
func createWorkerPool(numOfWorker int)  {
    var wg sync.WaitGroup
    for i := 0; i < numOfWorker; i++ {
        wg.Add(1)
        go worker(&wg)
    }
    wg.Wait()
    close(rltChan)
}

//将1至numOfJobs以内的整数依次写入jobsChan中
func allocate(numOfJobs int)  {
    for i := 1; i < numOfJobs; i++ {
        jobsChan <- i
    }
    close(jobsChan)
}

//显示所有的结果
func display(disChan chan bool)  {
    for result := range rltChan {
        fmt.Println(result)
    }
    disChan <- true
}

func main(){
    start := time.Now()
    //寻找素数的范围
    number := 2000
    //规定worker的个数
    numOfWorker := 10
    //确保输出显示全部完成
    disChan := make(chan bool)

    go allocate(number)

    go display(disChan)

    createWorkerPool(numOfWorker)

    //全部显示完毕
    <- disChan
    end := time.Now()
    diff := end.Sub(start)
    fmt.Println("耗费时间:",diff.Seconds())
}

有疑问加站长微信联系(非本文作者)

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

994 次点击  
加入收藏 微博
2 回复  |  直到 2024-09-27 10:13:37
jhuiren_jcplc
jhuiren_jcplc · #1 · 6月之前

改之前的,job%2 == 0 时不应该return,得continue,else里得也不是return,而是continue外层得for

myGoStudy
myGoStudy · #2 · 6月之前
jhuiren_jcplcjhuiren_jcplc #1 回复

改之前的,job%2 == 0 时不应该return,得continue,else里得也不是return,而是continue外层得for

醍醐灌顶!原来问题是这样。谢谢!

添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传