Golang for循环,i+的添加不一致+;
我和goroutines有个循环。我在循环中创建go例程,它打印一个字符串和一个int的“I”。我知道字符串和“I”将按随机顺序打印。但是,正如您在下面看到的,“i”并没有正确添加。五个字符串中的三个或四个的值保持不变,然后跳到2或1。不应该有一个1,2,3,4,5的随机顺序吗?我做错了什么Golang for循环,i+的添加不一致+;,go,Go,我和goroutines有个循环。我在循环中创建go例程,它打印一个字符串和一个int的“I”。我知道字符串和“I”将按随机顺序打印。但是,正如您在下面看到的,“i”并没有正确添加。五个字符串中的三个或四个的值保持不变,然后跳到2或1。不应该有一个1,2,3,4,5的随机顺序吗?我做错了什么 package main import ( "fmt" "sync" ) func main() { a := []string{ "apple",
package main
import (
"fmt"
"sync"
)
func main() {
a := []string{
"apple",
"orange",
"grape",
"peach",
"lemon",
}
wg := sync.WaitGroup{}
wg.Add(len(a))
i := 0
for _, v := range a {
go func(a string) {
fmt.Println(a, i)
i++
wg.Done()
}(v)
}
wg.Wait()
}
结果1:
orange 0
apple 0
lemon 0
peach 2
grape 0
结果2:
lemon 0
grape 0
peach 0
apple 0
orange 1
我的目标(随机顺序)
通过闭包,所有goroutine共享相同的变量
i
。试试这个:
package main
import (
"fmt"
"sync"
)
func main() {
a := []string{
"apple",
"orange",
"grape",
"peach",
"lemon",
}
wg := sync.WaitGroup{}
wg.Add(len(a))
for i, v := range a {
go func(a string, j int) {
fmt.Println(a, j)
wg.Done()
}(v,j)
}
wg.Wait()
}
通常情况下:在您发布的程序中,您正在从不同的goroutine读取i
并写入i
,而没有任何同步。这是一场数据竞赛。在这种情况下,任何事情都可能发生
围棋比赛检测器甚至对你大喊大叫
go run -race test.go
apple 0
==================
WARNING: DATA RACE
Read at 0x00c420010268 by goroutine 7:
main.main.func1()
/home/erwo/test.go:22 +0x6d
Previous write at 0x00c420010268 by goroutine 6:
main.main.func1()
/home/erwo/test.go:23 +0x191
Goroutine 7 (running) created at:
main.main()
/home/erwo/test.go:25 +0x15f
Goroutine 6 (finished) created at:
main.main()
/home/erwo/test.go:25 +0x15f
==================
orange 1
==================
WARNING: DATA RACE
Read at 0x00c420010268 by goroutine 8:
main.main.func1()
/home/erwo/test.go:22 +0x6d
Previous write at 0x00c420010268 by goroutine 6:
main.main.func1()
/home/erwo/test.go:23 +0x191
Goroutine 8 (running) created at:
main.main()
/home/erwo/test.go:25 +0x15f
Goroutine 6 (finished) created at:
main.main()
/home/erwo/test.go:25 +0x15f
==================
peach 2
grape 2
lemon 4
Found 2 data race(s)
exit status 66
通过闭包,所有goroutine共享相同的变量
i
。试试这个:
package main
import (
"fmt"
"sync"
)
func main() {
a := []string{
"apple",
"orange",
"grape",
"peach",
"lemon",
}
wg := sync.WaitGroup{}
wg.Add(len(a))
for i, v := range a {
go func(a string, j int) {
fmt.Println(a, j)
wg.Done()
}(v,j)
}
wg.Wait()
}
通常情况下:在您发布的程序中,您正在从不同的goroutine读取i
并写入i
,而没有任何同步。这是一场数据竞赛。在这种情况下,任何事情都可能发生
围棋比赛检测器甚至对你大喊大叫
go run -race test.go
apple 0
==================
WARNING: DATA RACE
Read at 0x00c420010268 by goroutine 7:
main.main.func1()
/home/erwo/test.go:22 +0x6d
Previous write at 0x00c420010268 by goroutine 6:
main.main.func1()
/home/erwo/test.go:23 +0x191
Goroutine 7 (running) created at:
main.main()
/home/erwo/test.go:25 +0x15f
Goroutine 6 (finished) created at:
main.main()
/home/erwo/test.go:25 +0x15f
==================
orange 1
==================
WARNING: DATA RACE
Read at 0x00c420010268 by goroutine 8:
main.main.func1()
/home/erwo/test.go:22 +0x6d
Previous write at 0x00c420010268 by goroutine 6:
main.main.func1()
/home/erwo/test.go:23 +0x191
Goroutine 8 (running) created at:
main.main()
/home/erwo/test.go:25 +0x15f
Goroutine 6 (finished) created at:
main.main()
/home/erwo/test.go:25 +0x15f
==================
peach 2
grape 2
lemon 4
Found 2 data race(s)
exit status 66
在每个goroutine中都会发生一些事情:
i
的值i
的值李>
无法保证这两件事是以原子的方式发生的,也不能保证这两件事是以什么顺序发生的
为了获得您想要的结果,您可以:
i
的访问(但这有时会破坏并行性)i
作为参数传递给函数(go func(i int){}(i)
)。(就像克罗姆的回答)我推荐两种。但我也建议不要使用goroutine顺序作为随机性的来源。在每个goroutine中都会发生一些事情:
i
的值i
的值李>
无法保证这两件事是以原子的方式发生的,也不能保证这两件事是以什么顺序发生的
为了获得您想要的结果,您可以:
i
的访问(但这有时会破坏并行性)i
作为参数传递给函数(go func(i int){}(i)
)。(就像克罗姆的回答)我推荐两种。但我也建议不要使用goroutine顺序作为随机性的来源。谢谢。我真正的程序是处理数千行,这就是为什么我想在for循环中使用go例程来节省时间。克罗姆的例子对我很有用。谢谢你更好的解释,谢谢。我真正的程序是处理数千行,这就是为什么我想在for循环中使用go例程来节省时间。克罗姆的例子对我很有用。谢谢你更好的解释,谢谢你给我解释。我听说了一个比赛条件,但直到现在才明白。谢谢你向我解释。我听说过比赛的情况,但直到现在才明白。