简体   繁体   English

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

[英]Multiple goroutines reading from a channel gives wrong data count

I'm working on a program where I read a csv file and do below operations:我正在开发一个程序,在其中读取 csv 文件并执行以下操作:

Full Code is available at: Here完整代码可在:这里

My CSV file is available at: CSV file我的 CSV 文件位于: CSV 文件

The problem is sometimes I get the correct count for A and B and sometimes I get the wrong count.问题是有时我得到 A 和 B 的正确计数,有时我得到错误的计数。

I think I'm doing something wrong in Goroutines and channels communication.我想我在 Goroutines 和渠道通信方面做错了。

When I comment the 2nd goroutine, I get correct result of 1st Goroutine.当我评论第二个 goroutine 时,我得到了第一个 Goroutine 的正确结果。 But when I uncomment 2nd Goroutine, I get incorrect output of Goroutine 1 and 2 both.但是当我取消注释第二个 Goroutine 时,我得到了 Goroutine 1 和 2 的错误输出。

Can anyone please explain what wrong I'm doing?谁能解释一下我做错了什么?

Also when I do go run -race main.go, the result shows me a race condition.此外,当我执行 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!")
}

In both cases, your wg.Done() is being called immediately after you start the goroutine.在这两种情况下,您的 wg.Done() 都会在您启动 goroutine 后立即被调用。 This means that your WaitGroup is not waiting for the goroutine to finish.这意味着您的 WaitGroup 不会等待 goroutine 完成。 Remember that the calling process proceeds when you call a goroutine.请记住,调用过程会在您调用 goroutine 时继续进行。 Try putting the wg.Done() call inside the goroutine, when it's finished doing stuff.尝试将 wg.Done() 调用放在goroutine 中,当它完成工作时。

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

OR或者

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM