英文:
Odd thing when deal with goroutine
问题
有两个奇怪的事情。
-
我在切片中创建了1000个数字,但只打印了246,为什么是246?为什么不是1000?
-
如果我删除"log.Println("hey")"这一行,为什么只打印0?
我知道可能存在同步问题,但我以前没有编写过并发程序,有没有什么文章可以推荐?
import (
"log"
"runtime"
)
func main() {
count := 1000
slice := make([]int, count)
for i := 0; i <= count-1; i++ {
slice[i] = i
}
for _, v := range slice {
go echo(v)
}
log.Println("hey") // 如果删除这一行,它只会打印0
runtime.Gosched()
}
func echo(v int) {
log.Println(v)
}
英文:
There are two odd things.
-
I made 1000 numbers in slice but it just print 246,why 246?and why not 1000?
-
if I delete "log.Println("hey")"this line,why does it just print 0?
I know it may has sync problem,but i haven't write any concurrence programs before,so any article can recommend?
import (
"log"
"runtime"
)
func main() {
count := 1000
slice := make([] int,count)
for i := 0; i <= count-1; i++ {
slice[i] =i
}
for _,v := range slice{
go echo(v)
}
log.Println("hey")//if delete this line,it just print 0
runtime.Gosched()
}
func echo(v int) {
log.Println(v)
}
答案1
得分: 3
没有任何保证任何go例程在主例程完成之前运行。当主例程完成时,你的程序会退出,而不会等待你创建的所有go例程完成(甚至开始)。
修复这个问题的最简单方法是分配一个同步通道,将其传递给每个echo实例,并在日志语句之后向其写入一个令牌。然后,主线程应该在返回之前从该通道中读取count
个令牌。
英文:
There's no guarantee that any of the go routines run before your main routine completes. When the main routine completes, your program exits without waiting for all the go routines you created to complete (or even start).
The easiest way to fix this is to allocate a synchronization channel, pass it to each echo instance, and write a token to it after your log statement. Then the main thread should read count
tokens out of that channel before returning.
答案2
得分: 3
如果你退出主要的go routine,它不会等待任何已经在运行的go routine。你需要同步正在运行的go routine,在我看来,sync.WaitGroup 是一个正确的通用解决方案。
import (
"log"
"sync"
)
func main() {
count := 1000
slice := make([]int, count)
for i := 0; i <= count-1; i++ {
slice[i] = i
}
wg := new(sync.WaitGroup)
for _, v := range slice {
wg.Add(1)
go echo(v, wg)
}
wg.Wait()
}
func echo(v int, wg *sync.WaitGroup) {
defer wg.Done()
log.Println(v)
}
英文:
If you exit your main go routine, it doesn't wait for any go routines that are already running. You need to synchronize the running go routines and in my experience a sync.WaitGroup is the right general solution.
import (
"log"
"sync"
)
func main() {
count := 1000
slice := make([]int, count)
for i := 0; i <= count-1; i++ {
slice[i] = i
}
wg := new(sync.WaitGroup)
for _, v := range slice {
wg.Add(1)
go echo(v, wg)
}
wg.Wait()
}
func echo(v int, wg *sync.WaitGroup) {
defer wg.Done()
log.Println(v)
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论