美文网首页Go语言用例Go知识库go
golang语言异步通信之WaitGroup

golang语言异步通信之WaitGroup

作者: CodingCode | 来源:发表于2018-02-07 14:57 被阅读50次

golang语言异步通信之WaitGroup

简介

WaitGroup的用途是使得主线程一直阻塞等待直到所有相关的子goroutine都已经完成了任务。

sync.WaitGroup只有3个API

  1. Add() # 添加计数
  2. Done() # 减掉计数,等价于Add(-1),这样sync.WaitGroup只有两个API了
  3. Wait() # 阻塞直到计数为零

用法例子1:正常用法


var wg sync.WaitGroup

func foo1() {
    log.Println("entry foo1")
    time.Sleep(5 * time.Second)
    wg.Done()
    log.Println("exit foo1")
}


func foo2() {
    log.Println("entry foo2")
    time.Sleep(2 * time.Second)
    wg.Done()
    log.Println("exit foo2")
}

func main() {
    log.Println("entry main")

    wg.Add(1)
    go foo1()

    wg.Add(1)
    go foo2()

    log.Println("wg.Wait()")
    wg.Wait()
    
    log.Println("exit main")
}

主线程调用起两个子线程foo1和foo2并且等待他们的完成。
运行结果

2018/02/07 14:29:21 entry main
2018/02/07 14:29:21 wg.Wait()
2018/02/07 14:29:21 entry foo1
2018/02/07 14:29:21 entry foo2
2018/02/07 14:29:23 exit foo2
2018/02/07 14:29:26 exit foo1
2018/02/07 14:29:26 exit main

用法例子2:Done()过多

func main() {
    log.Println("entry main")

    var wg sync.WaitGroup
    wg.Done()

    log.Println("exit main")
}

在这个例子中,我们一上来就Done

$ go build && ./main
2018/02/07 14:33:59 entry main
panic: sync: negative WaitGroup counter

goroutine 1 [running]:
sync.(*WaitGroup).Add(0xc42006c060, 0xffffffffffffffff)
        /usr/local/go/src/sync/waitgroup.go:75 +0x134
sync.(*WaitGroup).Done(0xc42006c060)
        /usr/local/go/src/sync/waitgroup.go:100 +0x34
main.main()
        /path_to/main.go:30 +0x89

计数器小于零,panic

用法例子3:Done()过少

var wg sync.WaitGroup

func foo1() {
    log.Println("entry foo1")
    time.Sleep(5 * time.Second)
    //wg.Done()
    log.Println("exit foo1")
}


func foo2() {
    log.Println("entry foo2")
    time.Sleep(2 * time.Second)
    //wg.Done()
    log.Println("exit foo2")
}

func main() {
    log.Println("entry main")

    wg.Add(1)
    go foo1()

    wg.Add(1)
    go foo2()

    log.Println("wg.Wait()")
    wg.Wait()
    
    log.Println("exit main")
}

这个例子中我们注释掉了两个子线程中的Done()函数,运行结果:

$ go build && ./wg 
2018/02/07 14:36:03 entry main
2018/02/07 14:36:03 wg.Wait()
2018/02/07 14:36:03 entry foo2
2018/02/07 14:36:03 entry foo1
2018/02/07 14:36:05 exit foo2
2018/02/07 14:36:08 exit foo1
fatal error: all goroutines are asleep - deadlock!

goroutine 1 [semacquire]:
sync.runtime_Semacquire(0x55ad7c)
        /usr/local/go/src/runtime/sema.go:56 +0x39
sync.(*WaitGroup).Wait(0x55ad70)
        /usr/local/go/src/sync/waitgroup.go:131 +0x72
main.main()
        /path_to/main.go:36 +0x127

这个错误表明,在最后一个活动线程foo1退出的时候,go检测到当前没有还在运行的线程,而还有在等待的线程,所以必然发生了死锁现象,这是go的一种自我保护机制。

相关文章

  • golang语言异步通信之WaitGroup

    golang语言异步通信之WaitGroup 简介 WaitGroup的用途是使得主线程一直阻塞等待直到所有相关的...

  • golang语言异步通信之Channel

    golang语言异步通信之Channel 简介 Channel主要用在go routine之间作为异步通信工具。简...

  • golang sync WaitGroup

    刚才看golang的sync的包,看见一个很有用的功能。就是WaitGroup。 先说说WaitGroup的用途:...

  • (八)golang WaitGroup 源码分析

    1 前言 WaitGroup是Golang应用开发过程中经常使用的并发控制技术。WaitGroup,可理解为Wai...

  • Golang 之 WaitGroup 源码解析

    前言 如果我们有一个大的任务要做,我们会尝试将这个任务分解,分解完成之后并发交由 goroutine 去做,并且我...

  • golang之sync包之WaitGroup

    sync包 sync是synchronization同步这个词的缩写,所以也会叫做同步包。这里提供了基本同步的操作...

  • golang sync WaitGroup

    简介 它能够一直等到所有的goroutine执行完成,并且阻塞主线程的执行,直到所有的goroutine执行完成。...

  • PHP实现基于Swoole简单的HTTP服务器

    引用Swoole官方定义: PHP语言的异步、并行、高性能网络通信框架,使用纯C语言编写,提供了PHP语言的异步多...

  • swoole

    什么是swoole swoole是PHP的异步、并行、高性能网络通信引擎,使用纯C语言编写,提供了PHP语言的异步...

  • golang之sync.WaitGroup示例

    下面一段代码 len(m) 不一定会打印为 10,为什么?。如果想要 len(m) 打印为 10,应该怎么修改代码...

网友评论

    本文标题:golang语言异步通信之WaitGroup

    本文链接:https://www.haomeiwen.com/subject/nioozxtx.html