为了账号安全,请及时绑定邮箱和手机立即绑定

与 for 循环和匿名函数的并发行为异常

与 for 循环和匿名函数的并发行为异常

Go
料青山看我应如是 2022-01-04 21:21:19
我已经找到了一种让代码按照我想要的方式运行的方法,但我想了解它为什么会这样,以便我对 Go 并发性的理解有所提高。我正在测试sync.WaitGroup等待一些 goroutine 完成,因为我计划以这种方式多次上传到 Amazon S3。这是我最初的代码:func main() {    var wg sync.WaitGroup    for i := 1; i <= 5; i++ {        wg.Add(1)        go func() {            fmt.Println(i)            time.Sleep(time.Second * 1)            wg.Done()        }()    }    wg.Wait()}我很惊讶地看到输出是:6, 6, 6, 6, 6。而不是像:2, 4, 1, 5, 3。由于循环甚至没有达到 6,这对我来说毫无意义。后来我将该i变量作为参数传递给匿名函数,然后它的行为符合我的预期。为什么会发生这种情况?我不明白。
查看完整描述

2 回答

?
拉丁的传说

TA贡献1789条经验 获得超8个赞

在这种情况下,在 for 循环完成之前,不会调度任何 goroutine。为了使 for 循环中断,i必须不小于或等于 5,因此在该点为 6。当 goroutine 运行时,它们每个都会打印i在闭包中捕获的单个变量的值。

当您将i参数作为参数传递给函数时,您将当前值复制到一个新变量中,并捕获当时的值。


查看完整回答
反对 回复 2022-01-04
?
慕侠2389804

TA贡献1719条经验 获得超6个赞

要回答您的问题,您必须传入i您的,func以便每个例程都有自己的i.


所以你的代码应该是这样的


func main() {

    var wg sync.WaitGroup


    for i := 1; i <= 5; i++ {

        wg.Add(1)

        go func(i int) {

            fmt.Println(i)

            time.Sleep(time.Second * 1)

            wg.Done()

        }(i)

    }


    wg.Wait()

}

我编写了这个实用程序函数来帮助并行化一组函数:


import "sync"


// Parallelize parallelizes the function calls

func Parallelize(functions ...func()) {

    var waitGroup sync.WaitGroup

    waitGroup.Add(len(functions))


    defer waitGroup.Wait()


    for _, function := range functions {

        go func(copy func()) {

            defer waitGroup.Done()

            copy()

        }(function)

    }

}

所以在你的情况下,我们可以这样做


func main() {

    functions := []func(){}

    for i := 1; i <= 5; i++ {

            function := func(i int) func() {

                return func() {

                        fmt.Println(i)

                }

            }(i)


        functions = append(functions, function)

    }


    Parallelize(functions...)


    fmt.Println("Done")

}

如果你想使用 Parallelize 功能,你可以在这里找到它https://github.com/shomali11/util


查看完整回答
反对 回复 2022-01-04
  • 2 回答
  • 0 关注
  • 143 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信