我尝试用并行goroutines编写一个复杂的程序。这是我的第一个带有通道的程序;)每个goroutine返回一个数组,不幸的是,结果是“随机”。如果我运行该程序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) }
此修复程序有两个部分,不要在goroutines之间共享切片,然后在中queue同步范围main。
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) }
没有x必要在goroutine之间共享额外的片段。如果每个goroutine需要另一个切片,则为每个切片定义一个新切片。共享单个片总是需要额外的同步。
x
另一场比赛是在从追加queue到slice切片的goruoutine 和决赛之间fmt.Println。没有理由并发执行这些操作,因为您不希望在读取所有值之前就进行打印,因此请在打印最终值之前完全完成for- range循环。
slice
fmt.Println