• sync.WaitGroup的使用以及坑


    all goroutines are asleep - deadlock 

    简单使用:

    package main
    
    import (
        "sync"
    )
    
    type httpPkg struct{}
    
    func (httpPkg) Get(url string) {}
    
    var http httpPkg
    
    func main() {
        var wg sync.WaitGroup
        var urls = []string{
            "http://www.golang.org/",
            "http://www.google.com/",
            "http://www.somestupidname.com/",
        }
        for _, url := range urls {
            // Increment the WaitGroup counter.
            wg.Add(1)
            // Launch a goroutine to fetch the URL.
            go func(url string) {
                // Decrement the counter when the goroutine completes.
                defer wg.Done()
                // Fetch the URL.
                http.Get(url)
            }(url)
        }
        // Wait for all HTTP fetches to complete.
        wg.Wait()
    }
    

    这是golang官网上的例子

    跟java的CountdownLatch差不多,也是阻塞等待所有任务完成之后再继续执行。

    简单使用就是在创建一个任务的时候wg.Add(1), 任务完成的时候使用wg.Done()来将任务减一。使用wg.Wait()来阻塞等待所有任务完成。

    然后我就写了一个例子:

    func main() {
        var wg sync.WaitGroup
        ch := make(chan int, 1000)
        for i := 0; i < 1000; i++ {
            wg.Add(1)
            go doSomething(i, wg, ch)
        }
        wg.Wait()
        fmt.Println("all done")
        for i := 0; i < 1000; i++ {
            dd := <-ch
            fmt.Println("from ch:"+strconv.Itoa(dd))
        }
    }
    
    func doSomething(index int, wg  sync.WaitGroup, ch chan int) {
        defer wg.Done()
        fmt.Println("start done:" + strconv.Itoa(index))
        //time.Sleep(20 * time.Millisecond)
        ch <- index
    }
    

    然后就报错了:

    fatal error: all goroutines are asleep - deadlock!
    goroutine 1 [semacquire]:
    sync.runtime_Semacquire(0xc42001608c)
        /usr/local/Cellar/go/1.10.3/libexec/src/runtime/sema.go:56 +0x39
    sync.(*WaitGroup).Wait(0xc420016080)
        /usr/local/Cellar/go/1.10.3/libexec/src/sync/waitgroup.go:129 +0x72
    main.main()
        /Users/taoli/go/src/github.com/c60/cai/tx_gorutine.go:16 +0xea
    

    怎么回事,他说死锁了。
    原来这是说,所有的协程都运行完了,你这边还在等待。

    什么原因导致的呢?
    原来是golang里如果方法传递的不是地址,那么就会做一个拷贝,所以这里调用的wg根本就不是一个对象。

    传递的地方传递地址就可以了:

    go doSomething(i, &wg, ch)
    
    func doSomething(index int, wg *sync.WaitGroup, ch chan int) {


    作者:ironman_
    链接:https://www.jianshu.com/p/4c2c80076094
    来源:简书
    著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
  • 相关阅读:
    HTTP响应状态码记录
    Linux给指定用户或全部用户(已登录)发送消息
    JS面向对象的程序设计
    Linux下查看/管理当前登录用户及用户操作历史记录
    JS Math对象中一些小技巧
    Linux常用命令学习
    Python学习问题记录
    Python中dir()与help()的使用
    webdriver常用API
    数据库备份表
  • 原文地址:https://www.cnblogs.com/brady-wang/p/13098977.html
Copyright © 2020-2023  润新知