如何使用Golang WaitGroup和mutex实现并发控制_组合同步工具管理任务

发布时间 - 2025-12-29 00:00:00    点击率:
Go 中 sync.WaitGroup 与 sync.Mutex 组合可协调 goroutine 生命周期与共享资源访问:WaitGroup 通过 Add/Wait/Done 控制任务启停,Mutex 通过锁机制防止数据竞争,二者分工明确、配合自然。

使用 Go 的 sync.WaitGroupsync.Mutex 组合,能有效协调多个 goroutine 的生命周期与共享资源访问——WaitGroup 负责“等任务完成”,Mutex 负责“防数据竞争”,二者分工明确,配合自然。

WaitGroup 控制任务启停节奏

WaitGroup 适合管理一组并发任务的启动与等待。它不关心任务内部逻辑,只跟踪“谁还没结束”。核心是三个方法:Add()(预设任务数)、Done()(标记完成)、Wait()(阻塞直到全部完成)。

  • 必须在启动 goroutine 前调用 Add(1),不能在 goroutine 内部 Add —— 否则可能 Wait 提前返回
  • Done() 应该和 Add(1) 严格配对;推荐用 defer wg.Done() 避免遗漏
  • WaitGroup 本身不是线程安全的:Add 和 Wait 不能并发调用;Add 必须在所有 goroutine 启动前完成

Mutex 保护共享状态不被并发篡改

当多个 goroutine 共同更新一个变量(如计数器、切片、map)时,必须用 Mutex 加锁。它不控制执行顺序,只确保同一时刻最多一个 goroutine 进入临界区。

  • 锁的粒度要合适:太粗(如整个函数加锁)会降低并发性;太细(每行都 lock/unlock)易出错且无必要
  • 优先使用 mu.Lock()/mu.Unlock() 配对,或更稳妥地用 defer mu.Unlock()
  • 避免死锁:不要在持有锁时调用可能再次获取同一把锁的函数;不要在锁内长时间阻塞(如网络请求、time.Sleep)

组合使用:一边等结果,一边安全更新状态

典型场景是并发处理一批数据,并汇总结果(比如统计成功/失败数量、收集返回值)。WaitGroup 确保主协程不提前退出,Mutex 保证汇总操作线程安全。

示例逻辑:

  • 定义全局计数器和互斥锁:var success, fail int; var mu sync.Mutex
  • 启动 N 个 goroutine,每个执行任务后根据结果调用 mu.Lock(); success++; mu.Unlock() 或类似操作
  • 主 goroutine 调用 wg.Wait() 后,再安全读取 successfail

注意:不要把 mu.Lock() 放在 WaitGroup 的 Add/Wait 调用路径上——它们无需同步,加锁只会拖慢调度。

替代方案与注意事项

对于简单计数,可考虑 sync/atomic(如 atomic.AddInt64),它比 Mutex 更轻量且无锁;但仅适用于基础类型和有限操作。若需复杂结构(如向切片追加、修改 map),仍需 Mutex。

另外,WaitGroup 无法取消或超时;如有此需求,应结合 context.Context 控制 goroutine 生命周期,WaitGroup 仅用于收尾等待。


# go  # golang  # 工具  # ai  # 无锁  # 有锁  # int  # 线程  # var  # 切片  # map  # 并发  # 多个  # 加锁  # 死锁  # 它不  # 放在  # 最多  # 如有  # 不要在  # 长时间  # 适用于 


相关栏目: 【 网站优化151355 】 【 网络推广146373 】 【 网络技术251813 】 【 AI营销90571


相关推荐: 制作公司内部网站有哪些,内网如何建网站?  开心动漫网站制作软件下载,十分开心动画为何停播?  如何实现建站之星域名转发设置?  jquery插件bootstrapValidator表单验证详解  Laravel如何使用Passport实现OAuth2?(完整配置步骤)  香港代理服务器配置指南:高匿IP选择、跨境加速与SEO优化技巧  北京专业网站制作设计师招聘,北京白云观官方网站?  宙斯浏览器文件分类查看教程 快速筛选视频文档与图片方法  js代码实现下拉菜单【推荐】  音响网站制作视频教程,隆霸音响官方网站?  jQuery 常见小例汇总  Laravel怎么使用Markdown渲染文档_Laravel将Markdown内容转HTML页面展示【实战】  晋江文学城电脑版官网 晋江文学城网页版直接进入  Laravel如何发送邮件和通知_Laravel邮件与通知系统发送步骤  Laravel Eloquent关联是什么_Laravel模型一对一与一对多关系精讲  HTML透明颜色代码怎么让下拉菜单透明_下拉菜单透明背景指南【技巧】  海南网站制作公司有哪些,海口网是哪家的?  佛山企业网站制作公司有哪些,沟通100网上服务官网?  Laravel如何创建自定义中间件?(Middleware代码示例)  如何用PHP工具快速搭建高效网站?  Laravel怎么实现模型属性的自动加密  如何在阿里云香港服务器快速搭建网站?  Laravel怎么实现前端Toast弹窗提示_Laravel Session闪存数据Flash传递给前端【方法】  如何在IIS中新建站点并解决端口绑定冲突?  php后缀怎么变mp4格式错误_修改扩展名提示格式不对怎么办【技巧】  Python函数文档自动校验_规范解析【教程】  bootstrap日历插件datetimepicker使用方法  JavaScript常见的五种数组去重的方式  html5的keygen标签为什么废弃_替代方案说明【解答】  HTML5空格和nbsp有啥关系_nbsp的作用及使用场景【说明】  网页制作模板网站推荐,网页设计海报之类的素材哪里好?  javascript中的try catch异常捕获机制用法分析  网站图片在线制作软件,怎么在图片上做链接?  Laravel如何实现一对一模型关联?(Eloquent示例)  Laravel Eloquent模型如何创建_Laravel ORM基础之Model创建与使用教程  如何注册花生壳免费域名并搭建个人网站?  php打包exe后无法访问网络共享_共享权限设置方法【教程】  实例解析angularjs的filter过滤器  如何为不同团队 ID 动态生成多个独立按钮  图片制作网站免费软件,有没有免费的网站或软件可以将图片批量转为A4大小的pdf?  如何在搬瓦工VPS快速搭建网站?  Laravel如何实现密码重置功能_Laravel密码找回与重置流程  惠州网站建设制作推广,惠州市华视达文化传媒有限公司怎么样?  Laravel怎么为数据库表字段添加索引以优化查询  微信小程序 canvas开发实例及注意事项  Python自然语言搜索引擎项目教程_倒排索引查询优化案例  Laravel安装步骤详细教程_Laravel环境搭建指南  INTERNET浏览器怎样恢复关闭标签页_INTERNET浏览器标签恢复快捷键与方法【指南】  Chrome浏览器标签页分组怎么用_谷歌浏览器整理标签页技巧【效率】  Laravel怎么进行数据库回滚_Laravel Migration数据库版本控制与回滚操作