duancong2965 2019-01-01 09:20
浏览 43

从通道读取多个goroutine导致错误的数据计数

I'm working on a program where I read a csv file and do below operations:

Full Code is available at:Here

My CSV file is available at: CSV file

The problem is sometimes I get the correct count for A and B and sometimes I get the wrong count.

I think I'm doing something wrong in Goroutines and channels communication.

When I comment the 2nd goroutine, I get correct result of 1st Goroutine. But when I uncomment 2nd Goroutine, I get incorrect output of Goroutine 1 and 2 both.

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.

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!")
}
  • 写回答

1条回答 默认 最新

  • dongpa3109 2019-01-01 10:21
    关注

    In both cases, your wg.Done() is being called immediately after you start the goroutine. This means that your WaitGroup is not waiting for the goroutine to finish. Remember that the calling process proceeds when you call a goroutine. Try putting the wg.Done() call inside the goroutine, when it's finished doing stuff.

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

    OR

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

报告相同问题?

悬赏问题

  • ¥30 Unity接入微信SDK 无法开启摄像头
  • ¥20 有偿 写代码 要用特定的软件anaconda 里的jvpyter 用python3写
  • ¥20 cad图纸,chx-3六轴码垛机器人
  • ¥15 移动摄像头专网需要解vlan
  • ¥20 access多表提取相同字段数据并合并
  • ¥20 基于MSP430f5529的MPU6050驱动,求出欧拉角
  • ¥20 Java-Oj-桌布的计算
  • ¥15 powerbuilder中的datawindow数据整合到新的DataWindow
  • ¥20 有人知道这种图怎么画吗?
  • ¥15 pyqt6如何引用qrc文件加载里面的的资源