登录
首页 >  Golang >  Go问答

从通道读取的多个 goroutine 给出错误的数据计数

来源:stackoverflow

时间:2024-04-22 10:00:34 278浏览 收藏

从现在开始,努力学习吧!本文《从通道读取的多个 goroutine 给出错误的数据计数》主要讲解了等等相关知识点,我会在golang学习网中持续更新相关的系列文章,欢迎大家关注并积极留言建议。下面就先一起来看一下本篇正文内容吧,希望能帮到你!

问题内容

我正在开发一个程序,在其中读取 csv 文件并执行以下操作:

完整代码位于:此处

我的 csv 文件位于: csv 文件

问题是有时我得到 a 和 b 的正确计数,有时却得到错误的计数。

我认为我在 goroutines 和通道通信中做错了什么。

当我评论第二个 goroutine 时,我得到了第一个 goroutine 的正确结果。但是当我取消注释 2nd goroutine 时,我得到了 goroutine 1 和 2 的错误输出。

谁能解释一下我做错了什么吗?

此外,当我执行 go run -race main.go 时,结果会显示竞争条件。

func main() {
    input, err := os.Open("CSV.csv")
    if err != nil {
        fmt.Println("Error while opening CSV file.")
        return
    }
    defer input.Close()

    formattedStartDateRange,err := time.Parse(time.RFC3339, startDateRange)
    if err != nil {
        fmt.Println(err)
    }

    formattedendDateRange,err := time.Parse(time.RFC3339, endDateRange)
    if err != nil {
        fmt.Println(err)
    }

    reader := csv.NewReader(input)
    reader.FieldsPerRecord = -1
    files := make(map[string]chan []string)

    wg := &sync.WaitGroup{}

    var line []string
    for line, err = reader.Read(); err == nil; line, err = reader.Read() {
        ch, ok := files[line[0]]
        if ok {
            ch <- line
        } else {
            ch = make(chan []string, 8)
            ch <- line
            wg.Add(2) // Must wait for 2 calls to 'done' before moving on

            go func() {
                UserMapMutex.Lock()
                if (findNumberOfBuilds(formattedStartDateRange, formattedendDateRange, ch, wg)) {
                    totalBuildCount++
                }
                UserMapMutex.Unlock()
                wg.Done()
            }()

            go func() {
                UserMapMutex.Lock()
                countUserBuildFrequency(ch, wg)
                UserMapMutex.Unlock()
                wg.Done()
            }()


            files[line[0]] = ch
        }
    }


    if err.Error() != "EOF" {
        fmt.Println("Error while reading CSV file.")
        return
    }
    for _, ch := range files {
        close(ch)
    }
    wg.Wait()

    fmt.Println("Total Build executed from 1st November to 30th November =", totalBuildCount)
    fmt.Println("Total Build", userBuildFreq["5c00a8f685db9ec46dbc13d7"])
    fmt.Println("Done!")
}

解决方案


在这两种情况下,您的 wg.done() 在启动 goroutine 后立即被调用。这意味着您的 waitgroup 不会等待 goroutine 完成。请记住,当您调用 goroutine 时,调用过程就会继续。当 goroutine 完成工作时,尝试将 wg.done() 调用放入 goroutine 内部。

go func(wg) {
    // do stuff
    wg.done
}

或者

go func(wg) {
    defer wg.Done
    // do stuff
}

文中关于的知识介绍,希望对你的学习有所帮助!若是受益匪浅,那就动动鼠标收藏这篇《从通道读取的多个 goroutine 给出错误的数据计数》文章吧,也可关注golang学习网公众号了解相关技术文章。

声明:本文转载于:stackoverflow 如有侵犯,请联系study_golang@163.com删除
相关阅读
更多>
最新阅读
更多>
课程推荐
更多>