使用for循环和匿名函数执行并发性的行为意外 [英] Go concurrency with for loop and anonymous function behaves unexpectedly
问题描述
我已经找到了代码行为的一种方法,但我想知道为什么它的行为如此,以至于我对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
变量作为参数
传递给匿名函数,然后按照我的预期行事。
为什么会发生这种情况?我不理解它。 解决方案
常见问题解答:以goroutine的形式运行的闭包会发生什么情况?
在这种情况下,没有一个goroutines会被安排到for循环完成。为了使for循环中断 i
不能小于或等于5,因此在那个点上是6。当goroutines运行时,它们每个都打印在闭包中捕获的单变量 i
的值。
当您将 i
作为参数传递给函数时,将当前值复制到一个新变量中,捕获当时的价值。
I have already found out a way for the code to behave as I want, but I would like to understand why it behaves like this so that my understanding of Go concurrency improves.
I was testing out sync.WaitGroup
to wait for some goroutines to finish because I plan on doing multiple uploads to Amazon S3 in this way.
This was the code I had originally:
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()
}
I was surprised to see that the output was: 6, 6, 6, 6, 6
.
Instead of something like: 2, 4, 1, 5, 3
.
Since the loop does not even go to 6, this made no sense to me.
I later passed the i
variable to the anonymous function as argument
and then it behaved as I expected.
Why does this happen? I don't understand it.
This is covered in the faq: What happens with closures running as goroutines?
In this case, none of the goroutines get scheduled until the for loop completes. In order for the for loop to break i
must not be less than or equal to 5, therefore it is 6 at that point. When the goroutines run, they each print the value of the single variable i
which is captured in the closures.
When you pass i
as an argument to the function, you copy the current value to a new variable, capturing the value at that moment.
这篇关于使用for循环和匿名函数执行并发性的行为意外的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!