Go并发编程-WaitGroup

一、前言

go语言类似Java JUC包也提供了一些列用于多线程之间进行同步的措施,比如低级的同步措施有 锁、CAS、原子变量操作类。相比Java来说go提供了独特的基于通道的同步措施。本节我们先来看看go中WaitGroup

二、WaitGroup

在日常开发中经常会遇到这样的情况,就是一个线程需要等其他几个线程执行完毕后在执行一件事,比如常见的是在一个线程中切分一个大任务为几个小任务,然后多个子任务并发运行,切分线程则需要等子任务全部运行完毕后做汇总。

在go中sync包中的WaitGroup就可以来做多goroutine之间的同步,WaitGroup类似Java JUC包中的CyclicBarrier 、CountDownLatch、Semaphore。

在go中使用wg sync.WaitGroup就可以创建一个WaitGroup组,其方法 func(wg*WaitGroup)Add(deltaint)作用可以认为是设置信号量个数, (wg*WaitGroup)Done()可以认为是让信号量个数减去1, (wg*WaitGroup)Wait()方法会一直阻塞,直到信号量变为了0。

需要注意调用Add方法时候如果delta传递为负数会抛出异常 panic:sync:negativeWaitGroupcounter。另外调用Add设置信号量的个数必须先于有goroutine调用其Wait方法。

下面我们看一个例子:

 package main
import (
    "fmt"
    "sync"
)
var (
    wg   sync.WaitGroup //信号量
    task []int//任务切片
)
func main() {
    //1. threadNum个信号量
    wg.Add(2)
    task := []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
    //2.开启2个goroutine
    go subTask(task, 1, 5)
    go subTask(task, 6, 10)
    //3.等待子任务执行完毕
    wg.Wait()
    fmt.Println("task over")
}
func subTask(task []int, start int, end int) {
    defer wg.Done()
    for i := start - 1; i <= end-1; i++ {
        fmt.Println(task[i])
    }
}
  • 如上代码首先创建了2个信号量和一个切片

  • 然后开启了两个goroutine分别执行subTask函数,subTask函数第一个参数是任务切片,后两个参数是要该方法访问切片中那些元素的索引范围

  • subTask内打印完对应的元素后,让信号量减去1,代码3则等待两个goroutine执行完毕后返回。

另外如果需要复用WaitGroup需要确保调用Add方法要晚于原来的Wait方法返回:

package main
import (
    "fmt"
    "sync"
)
var (
    wg   sync.WaitGroup //信号量
    task []int          //任务切片
)
func main() {
    //1. threadNum个信号量
    wg.Add(2)
    task := []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
    //2.开启2个goroutine
    go subTask(task, 1, 5)
    go subTask(task, 6, 10)
    //3.等待子任务执行完毕
    wg.Wait()
    fmt.Println("-----")
    //4.复用wg,创建三个信号量
    wg.Add(3)
    go subTask(task, 1, 3)
    go subTask(task, 4, 6)
    go subTask(task, 7, 10)
    //5.等待3个任务执行完毕
    wg.Wait()
    fmt.Println("task over")
}
func subTask(task []int, start int, end int) {
    defer wg.Done()
    for i := start - 1; i <= end-1; i++ {
        fmt.Println(task[i])
    }
}

如上代码4复用了wg,这个发生在代码3返回后。

假期在家无聊?那就免费学习下Go语言吧!!!

Go并发编程-并发与并行

Go并发编程-并发编程难在哪里

Go并发编程-线程模型

Go并发编程-内存模型

Go并发编程-goroutine轻量级的线程

Go并发编程-runtime包

Go并发编程-互斥锁

Go并发编程-读写锁

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值