golang语言异步通信之WaitGroup

2024-05-14 02:48

本文主要是介绍golang语言异步通信之WaitGroup,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

golang语言异步通信之WaitGroup

96 CodingCode 关注

2018.02.07 14:57 字数 267 阅读 88评论 0喜欢 0

golang语言异步通信之WaitGroup

简介

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

sync.WaitGroup只有3个API

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

用法例子1:正常用法


var wg sync.WaitGroupfunc 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.WaitGroupwg.Done()log.Println("exit main")
}

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

$ go build && ./main
2018/02/07 14:33:59 entry main
panic: sync: negative WaitGroup countergoroutine 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.WaitGroupfunc 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的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/987537

相关文章

python使用fastapi实现多语言国际化的操作指南

《python使用fastapi实现多语言国际化的操作指南》本文介绍了使用Python和FastAPI实现多语言国际化的操作指南,包括多语言架构技术栈、翻译管理、前端本地化、语言切换机制以及常见陷阱和... 目录多语言国际化实现指南项目多语言架构技术栈目录结构翻译工作流1. 翻译数据存储2. 翻译生成脚本

golang内存对齐的项目实践

《golang内存对齐的项目实践》本文主要介绍了golang内存对齐的项目实践,内存对齐不仅有助于提高内存访问效率,还确保了与硬件接口的兼容性,是Go语言编程中不可忽视的重要优化手段,下面就来介绍一下... 目录一、结构体中的字段顺序与内存对齐二、内存对齐的原理与规则三、调整结构体字段顺序优化内存对齐四、内

Go语言中三种容器类型的数据结构详解

《Go语言中三种容器类型的数据结构详解》在Go语言中,有三种主要的容器类型用于存储和操作集合数据:本文主要介绍三者的使用与区别,感兴趣的小伙伴可以跟随小编一起学习一下... 目录基本概念1. 数组(Array)2. 切片(Slice)3. 映射(Map)对比总结注意事项基本概念在 Go 语言中,有三种主要

C语言中自动与强制转换全解析

《C语言中自动与强制转换全解析》在编写C程序时,类型转换是确保数据正确性和一致性的关键环节,无论是隐式转换还是显式转换,都各有特点和应用场景,本文将详细探讨C语言中的类型转换机制,帮助您更好地理解并在... 目录类型转换的重要性自动类型转换(隐式转换)强制类型转换(显式转换)常见错误与注意事项总结与建议类型

异步线程traceId如何实现传递

《异步线程traceId如何实现传递》文章介绍了如何在异步请求中传递traceId,通过重写ThreadPoolTaskExecutor的方法和实现TaskDecorator接口来增强线程池,确保异步... 目录前言重写ThreadPoolTaskExecutor中方法线程池增强总结前言在日常问题排查中,

Go语言利用泛型封装常见的Map操作

《Go语言利用泛型封装常见的Map操作》Go语言在1.18版本中引入了泛型,这是Go语言发展的一个重要里程碑,它极大地增强了语言的表达能力和灵活性,本文将通过泛型实现封装常见的Map操作,感... 目录什么是泛型泛型解决了什么问题Go泛型基于泛型的常见Map操作代码合集总结什么是泛型泛型是一种编程范式,允

微服务架构之使用RabbitMQ进行异步处理方式

《微服务架构之使用RabbitMQ进行异步处理方式》本文介绍了RabbitMQ的基本概念、异步调用处理逻辑、RabbitMQ的基本使用方法以及在SpringBoot项目中使用RabbitMQ解决高并发... 目录一.什么是RabbitMQ?二.异步调用处理逻辑:三.RabbitMQ的基本使用1.安装2.架构

Android kotlin语言实现删除文件的解决方案

《Androidkotlin语言实现删除文件的解决方案》:本文主要介绍Androidkotlin语言实现删除文件的解决方案,在项目开发过程中,尤其是需要跨平台协作的项目,那么删除用户指定的文件的... 目录一、前言二、适用环境三、模板内容1.权限申请2.Activity中的模板一、前言在项目开发过程中,尤

C语言小项目实战之通讯录功能

《C语言小项目实战之通讯录功能》:本文主要介绍如何设计和实现一个简单的通讯录管理系统,包括联系人信息的存储、增加、删除、查找、修改和排序等功能,文中通过代码介绍的非常详细,需要的朋友可以参考下... 目录功能介绍:添加联系人模块显示联系人模块删除联系人模块查找联系人模块修改联系人模块排序联系人模块源代码如下

基于Go语言实现一个压测工具

《基于Go语言实现一个压测工具》这篇文章主要为大家详细介绍了基于Go语言实现一个简单的压测工具,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录整体架构通用数据处理模块Http请求响应数据处理Curl参数解析处理客户端模块Http客户端处理Grpc客户端处理Websocket客户端