Goroutines共享一个阵列通道:试图解决数据竞争问题

时间:2016-08-08 14:58:23

标签: arrays go parallel-processing channel

我尝试用并行的goroutine编写一个复杂的程序。这是我的第一个带有通道的程序;)每个goroutine返回一个数组,不幸的是,结果是" random"。如果我运行10次程序,我会得到10个不同的结果:(

这是对我的程序的过度简化,结果很好(可能因为它太简单了)但是当我使用-race参数运行它时,有4个数据竞争。

我尝试使用close()函数,但它没有用。

你可以帮我找错吗?非常感谢你提前!

package main

import "fmt"
import "sync"
import "strconv"


func cat_strings(a int, b string) []string{
    var y []string

    j := strconv.Itoa(a)
    y = append(y, j)
    y = append(y, b)
    return y
}

func main() {
    var slice []string
    var wg sync.WaitGroup
    var x []string

    queue := make(chan []string, 10)

    wg.Add(10)
    for i := 0; i < 10; i++ {
        go func(i int) {
            defer wg.Done()
            x = cat_strings(i, "var")
            queue <- x
        }(i)

    }
    //close(queue)

    go func() {
        defer wg.Done()
        for t := range queue {
            slice = append(slice, t...)
        }
    }()

    wg.Wait()
    fmt.Println(slice)
}

1 个答案:

答案 0 :(得分:7)

这个修补程序有两个部分,不要在goroutine之间共享切片,然后在queue中同步main范围内。

import (
    "fmt"
    "strconv"
    "sync"
)

func cat_strings(a int, b string) []string {
    var y []string

    j := strconv.Itoa(a)
    y = append(y, j)
    y = append(y, b)
    return y
}

func main() {
    var slice []string
    var wg sync.WaitGroup

    queue := make(chan []string, 10)

    wg.Add(10)
    for i := 0; i < 10; i++ {
        go func(i int) {
            defer wg.Done()
            queue <- cat_strings(i, "var")
        }(i)

    }

    go func() {
        wg.Wait()
        close(queue)
    }()

    for t := range queue {
        slice = append(slice, t...)
    }

    fmt.Println(slice)
}

你没有理由在goroutines之间分享额外的x切片。如果每个goroutine需要另一个切片,请为每个切片定义一个切片。共享单个片段总是需要额外的同步。

另一场比赛介于从queueslice切片附近的goruoutine和最终的fmt.Println之间。由于您不想在读取所有值之后进行打印,因此没有理由将它们并发,因此在打印最终值之前完全完成for-range循环。