首页 > 其他分享 >golang 中的 sync.WaitGroup

golang 中的 sync.WaitGroup

时间:2024-09-12 17:14:35浏览次数:8  
标签:wg WaitGroup goroutine sync golang 并发 完成

sync.WaitGroup 是 Go 标准库中的一个同步原语,用于协调多个 goroutine 的执行,确保它们在主线程或其他 goroutine继续执行之前完成任务。

sync.WaitGroup 的用法

1. 创建 WaitGroup 实例

在开始 goroutine 执行之前,需要创建一个 WaitGroup 实例。这个实例将用于跟踪正在运行的 goroutine 的数量。

var wg sync.WaitGroup

2. 添加任务

在启动 goroutine 之前,通过调用 Add 方法设置需要等待的任务数量。例如,如果有两个 goroutine 要执行,就需要调用 wg.Add(2)

wg.Add(1) // 启动一个新的 goroutine

3. 完成任务

每个 goroutine 在完成其任务时需要调用 Done 方法,以便减少计数器的数量。通常,这个调用在 goroutine 函数的最后。

go func() {
    defer wg.Done() // 在任务完成后调用 Done
    // 执行任务
}()

 

4. 等待任务完成

主线程或其他 goroutine 可以调用 Wait 方法,阻塞等待直到计数器变为零,即所有被跟踪的 goroutine 都完成了其执行。

wg.Wait() // 阻塞等待所有 goroutine 完成

 

示例代码

下面是一个示例,演示如何使用 sync.WaitGroup 来等待多个 goroutine 完成其执行:

package main

import (
    "fmt"
    "sync"
)

func main() {
    var wg sync.WaitGroup

    for i := 1; i <= 3; i++ {
        wg.Add(1) // 添加一个新的 goroutine 任务
        go func(i int) {
            defer wg.Done() // 完成任务时调用 Done
            fmt.Printf("Goroutine %d is running\n", i)
        }(i)
    }

    wg.Wait() // 等待所有 goroutine 完成
    fmt.Println("All goroutines completed")
}

展示如何使用 sync.WaitGroup 来处理多个并发的网络请求

package main

import (
    "fmt"
    "net/http"
    "sync"
    "io/ioutil"
)

// fetchData 从指定的 URL 获取数据
func fetchData(url string, wg *sync.WaitGroup, results chan<- string) {
    defer wg.Done() // 任务完成后调用 Done

    resp, err := http.Get(url)
    if err != nil {
        results <- fmt.Sprintf("Error fetching %s: %v", url, err)
        return
    }
    defer resp.Body.Close()

    body, err := ioutil.ReadAll(resp.Body)
    if err != nil {
        results <- fmt.Sprintf("Error reading response body from %s: %v", url, err)
        return
    }

    results <- fmt.Sprintf("Response from %s: %s", url, body)
}

func main() {
    urls := []string{
        "https://jsonplaceholder.typicode.com/posts/1",
        "https://jsonplaceholder.typicode.com/posts/2",
        "https://jsonplaceholder.typicode.com/posts/3",
    }

    var wg sync.WaitGroup
    results := make(chan string, len(urls)) // 缓冲通道,用于存储结果

    for _, url := range urls {
        wg.Add(1) // 添加一个新的 goroutine 任务
        go fetchData(url, &wg, results)
    }

    wg.Wait() // 等待所有 goroutine 完成
    close(results) // 关闭结果通道

    // 处理所有结果
    for result := range results {
        fmt.Println(result)
    }
}

代码解析

  1. fetchData 函数:

    • 这是一个并发执行的函数,用于从指定的 URL 获取数据。
    • 使用 defer wg.Done() 来通知 WaitGroup 这个 goroutine 完成了它的任务。
    • 通过 results 通道将获取到的数据或错误信息传递到主 goroutine。
  2. main 函数:

    • 定义了一组 URL 列表,程序将并发地从这些 URL 获取数据。
    • 使用 sync.WaitGroup 来确保所有的 fetchData goroutine 在继续之前完成。
    • 使用带缓冲的通道 results 来收集所有的响应结果。
    • 在所有请求完成后,关闭通道并处理所有结果。

这个例子中的 sync.WaitGroup 可以确保在所有的网络请求完成后才进行结果处理。在实际应用中,类似的模式可以用于多个并发的网络请求、并发计算、数据处理等任务,保证所有任务在继续执行后续步骤之前已经完成。

总结

sync.WaitGroup 通过计数器来协调多个 goroutine 的执行,它允许你在所有 goroutine 完成之前阻塞主线程或其他 goroutine。使用 WaitGroup 可以简化并发编程中的同步问题,确保所有并发操作完成后再继续执行后续代码。

标签:wg,WaitGroup,goroutine,sync,golang,并发,完成
From: https://www.cnblogs.com/-cyh/p/18410644

相关文章

  • 什么是golang中的channel
    在Go语言中,channel是一种用于在goroutine之间进行通信和同步的工具。它允许一个goroutine发送数据到channel,另一个goroutine从channel接收数据,从而实现并发编程中的数据交换。 Channel的关键特性类型安全:每个channel都有一个指定的类型,确保发送到channel的......
  • golang 的录音库
    一、PortAudio的go绑定【不推荐】https://github.com/gordonklaus/portaudio这个库有热度,但在Windows上需要从源码使用 VisualStudio或MinGW编译,比较麻烦。Beep库并没有录音功能,但有一个相关库 https://github.com/MarkKremer/microphone.git可以实现录音,然后使......
  • rsync 学习笔记(二)常见问题集锦
     问题一@ERROR:chrootfailedrsyncerror:errorstartingclient-serverprotocol(code5)atmain.c(1522)[receiver=3.0.3]原因服务器端的目录不存在或无权限。创建目录并修正权限可解决问题。问题二@ERROR:authfailedonmoduleteersyncerror:errorstarting......
  • rsync 学习笔记(一)编译
    一、背景 rsync二进制程序依赖外部库,由于安全问题,有时会单独升级依赖的外部库。另外为了防止因为栈溢出攻击导致服务器被黑,需要对rsync及其依赖的外部库重新编译,开启安全编译选项,增加黑客破解的复杂度。 所有的库编译必须要求加上如下编译选项:栈保护(-fstack-protector-al......
  • 3天学会golang的基础语法
     1.视频资料在线观看:【尚硅谷】Golang入门到实战教程丨一套精通GO语言_哔哩哔哩_bilibili2.学习目录 001_尚硅谷_Golang可以做什么.mp4002_尚硅谷_如何学习Golang更高效(1).mp4003_尚硅谷_如何学习Golang更高效(2).mp4004_尚硅谷_程序的基本概念.mp4005_尚硅谷_Go语......
  • 线程池以及详解使用@Async注解异步处理方法
    目录一.什么是线程池:二.使用线程池的好处:三.线程池的使用场景:四.使用线程池来提高Springboot项目的并发处理能力:1.在application.yml配置文件中配置:2.定义配置类来接受配置文件内的属性值:3.启用异步支持:4.实例: 五.详细解析@Async注解的使用:1.@Async注解作用:2.@Asyn......
  • 推荐一款好用的golang修复无效json的库:JSONRepair
    简单来说,就是可以将错误格式(非标准)的json修正,如下图所示: 我的json明显不是标准的json格式,是不能被解析的: 但是JSONRepair库也能修复。 github地址:https://github.com/kaptinlin/jsonrepair使用也非常简单:1、安装:gogetgithub.com/kaptinlin/jsonrepair2......
  • 中文关键字检索分析-导出到csv或者excel-多文件或文件夹-使用python和asyncio和pandas
    1.02版本把原来的tab一个个拼接成文件输出,改成pandas的dataframe使用asyncio库来使用协程,但是测试下来速度好像是差不多的。可能速度太快了,没能很好的测出来差异。原来的最初的代码是java版本的,现在用python重写一遍java版本使用completableFuture来异步IO,主要是文件输......
  • golang 合成的图片
    packagepicture_serviceimport( "errors" "github.com/nfnt/resize" "image" "image/draw" "image/jpeg" "image/png" "log" "net/http" "os")typePictureServi......
  • 避坑指南:Golang框架自动化测试中的常见问题与解决方案大全
    在使用Golang框架进行自动化测试的过程中,开发者常常会遇到各种各样的问题。为了帮助大家避免一些常见的坑,我整理了一份详细的避坑指南,希望能对大家的开发工作有所帮助。忽视测试用例的独立性在进行自动化测试时,很多人会犯的一个错误是让测试用例之间产生依赖。比如,测试用例A需......