douyimiao1993 2016-03-18 19:20
浏览 55
已采纳

在Go并行处理数组会产生意外结果

I am interested to calculate correlations in parallel in Go. The main problem I have is that all the Go processes seems to execute exactly the same calculation. I reproduced here the problem with a very simple example. I obtain :

 4 + 50 = 54 
 4 + 50 = 54 
 4 + 50 = 54 

instead of :

 1 + 20 = 21 
 2 + 30 = 32 
 3 + 40 = 43 

If I move up "wg.Wait()" I obtain the good result but no parallelism :( Thank's in advance for your comments !

   package main

    import (
        "fmt"
        "runtime"
        "sync"
    )

    func process_array(x, y int) int {
      r := x + y
      return r
    }


    func main() {
        a1 := []int{0, 1, 2, 3, 4}
        a2 := []int{10, 20, 30, 40, 50}

        runtime.GOMAXPROCS(8)
        var wg sync.WaitGroup

        for i := 1; i < 4 ; i++ {
            wg.Add(1)
            go func() {
                defer wg.Done()
                x :=process_array(a1[i],a2[i])
                fmt.Println(a1[i],"+", a2[i],"=", x)
            }()
            //wg.Wait() give the good result 
                        //but it is not parallel processing
                        // 1 + 20 = 21
                        // 2 + 30 = 32
                        // 3 + 40 = 43
          }
        wg.Wait() // give a repetition of the same result :
                  // 4 + 50 = 54
                  // 4 + 50 = 54
                  // 4 + 50 = 54

    }
  • 写回答

1条回答 默认 最新

  • dongyaobo9081 2016-03-18 19:24
    关注

    You're accessing the same copy of i in all goroutines. The output you see is because the loop happens to finish before any of the goroutines start executing.

    This means that i has the same value in all goroutines, i.e. the last value it had in the loop.

    Passing i as an argument to each of your goroutines, thereby operating on a copy per goroutine instead, solves this problem.

    The reason you saw the result you expected when you added wg.Wait() in the loop is because you then introduced synchronization, waiting for the goroutine to finish before starting the next one. That means the execution was in fact serial, not parallell.

    Here's the updated code, which works as you'd expect:

    package main
    
    import (
        "fmt"
        "runtime"
        "sync"
    )
    
    func process_array(x, y int) int {
        r := x + y
        return r
    }
    
    func main() {
        a1 := []int{0, 1, 2, 3, 4}
        a2 := []int{10, 20, 30, 40, 50}
    
        runtime.GOMAXPROCS(8)
        var wg sync.WaitGroup
    
        for i := 1; i < 4; i++ {
            wg.Add(1)
            go func(i int) {
                defer wg.Done()
                x := process_array(a1[i], a2[i])
                fmt.Println(a1[i], "+", a2[i], "=", x)
            }(i)
            //wg.Wait() give the good result
            //but it is not parallel processing
            // 1 + 20 = 21
            // 2 + 30 = 32
            // 3 + 40 = 43
        }
        wg.Wait() // give a repetition of the same result :
        // 4 + 50 = 54
        // 4 + 50 = 54
        // 4 + 50 = 54
    
    }
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 nginx中的CORS策略应该如何配置
  • ¥30 信号与系统实验:采样定理分析
  • ¥100 我想找人帮我写Python 的股票分析代码,有意请加mathtao
  • ¥20 Vite 打包的 Vue3 组件库,图标无法显示
  • ¥15 php 同步电商平台多个店铺增量订单和订单状态
  • ¥15 关于logstash转发日志时发生的部分内容丢失问题
  • ¥17 pro*C预编译“闪回查询”报错SCN不能识别
  • ¥15 微信会员卡接入微信支付商户号收款
  • ¥15 如何获取烟草零售终端数据
  • ¥15 数学建模招标中位数问题