sync.WaitGroup使用遇到的坑
一、问题
最近在写的一个小工具,需要使用到 goroutine 之间的同步等待问题。之前也写过 golang channel与sync.WaitGroup同步 ,当时测试的时候使用了下官方示例也可以正常执行,不过最近在该工具使用时调用该示例的方法进行使用时,发现出现了无法正常退出的问题。见下图:
上面是使用跟踪工具跟踪时的结果。发现正常调用也返回了想要的结果,但是最后看情形,应该是卡在main进程还在一直wait等待上。具体调用的主要代码类似如下:
1var wg sync.WaitGroup
2 lines := strings.Split(Ioutil(*ipfile), "\n")
3 fmt.Println(lines)
4 fmt.Println(len(lines))
5 //wg.Add(len(lines))
6 for _, r := range lines {
7 if r != "" {
8 wg.Add(1)
9 fmt.Println("value is" + r)
10 go Multrun(r, data, wg)
11 }
12 }
13 wg.Wait()
14 } else {
15 fmt.Printf("didn't hava ip address,use \t%s -h\n check", os.Args[0])
16 os.Exit(0)
17 }
18 }
19}
20func Multrun(ip string, data []byte, wg sync.WaitGroup) {
21 defer wg.Done()
22 url := "http://" + ip + ":10000"
23 x, _ := DoBytesPost(url, data)
24 fmt.Println(ip + "\n========================\n" + string(x))
25}
二、解决方法
后来在查找了很多资料以后,发现如下一段话:golang里如果方法传递的不是地址,那么就会做一个拷贝,所以这里调用的wg根本就不是一个对象。这句话啥意思呢?就是如果在方法里不传递对象的内存地址,传过去的内容就会变成一个新的对象,这就导致上面我们给给Multrun的wg sync.WaitGroup是一个新的对象,而老的在main里的对象是持续等待不到结束调用的指令的。如何解决呢?传内存地址给函数。
1go doSomething(i, &wg, ch)
2func doSomething(index int, wg *sync.WaitGroup, ch chan int) {
三、演示代码
1package main
2import (
3 "fmt"
4 "strconv"
5 "sync"
6)
7func main() {
8 var wg sync.WaitGroup
9 ch := make(chan int, 1000)
10 for i := 0; i < 1000; i++ {
11 wg.Add(1)
12 go doSomething(i, wg, ch)
13 }
14 wg.Wait()
15 fmt.Println("all done")
16 for i := 0; i < 1000; i++ {
17 dd := <-ch
18 fmt.Println("from ch:" + strconv.Itoa(dd))
19 }
20}
21func doSomething(index int, wg sync.WaitGroup, ch chan int) {
22 defer wg.Done()
23 fmt.Println("start done:" + strconv.Itoa(index))
24 //time.Sleep(20 * time.Millisecond)
25 ch <- index
26}
上面是一段演示代码,使用上面的代码直接运行时会报deadlock的错误,如下:
1fatal error: all goroutines are asleep - deadlock!
2goroutine 1 [semacquire]:
3sync.runtime_Semacquire(0xc4200b401c)
4 /usr/lib/golang/src/runtime/sema.go:56 +0x39
5sync.(*WaitGroup).Wait(0xc4200b4010)
6 /usr/lib/golang/src/sync/waitgroup.go:131 +0x72
7main.main()
8 /tmp/test/test.go:16 +0xe7
解决方法也比较简单,上面第二步已经分析过了,具体你可以修改试试让程序正常运行。
捐赠本站(Donate)
如您感觉文章有用,可扫码捐赠本站!(If the article useful, you can scan the QR code to donate))
- Author: shisekong
- Link: https://blog.361way.com/sync-waitgroup/6235.html
- License: This work is under a 知识共享署名-非商业性使用-禁止演绎 4.0 国际许可协议. Kindly fulfill the requirements of the aforementioned License when adapting or creating a derivative of this work.