goroutine生命周期管理

news/2025/3/26 4:46:56/文章来源:https://www.cnblogs.com/yubo-guan/p/18788941

目录
  • 1. 创建 goroutine
  • 2. goroutine 的生命周期
  • 3. 管理 goroutine 的生命周期
    • 3.1 使用 sync.WaitGroup 等待 goroutine 完成
    • 3.2 使用 context 控制 goroutine 的取消
    • 3.3 使用 channel 控制 goroutine 的退出
    • 3.4 避免 goroutine 泄漏
  • 4. 主 goroutine 的管理
  • 5. 总结


在 Go 语言中,goroutine 是一种轻量级的线程,由 Go 运行时(runtime)管理。goroutine 的生命周期从创建开始,到任务完成或主动退出结束。由于 goroutine 是并发执行的,管理它们的生命周期是编写高效、可靠并发程序的关键。

以下是 goroutine 生命周期的管理方法和注意事项:


1. 创建 goroutine

使用 go 关键字可以创建一个 goroutine。goroutine 会立即开始执行指定的函数。

go func() {fmt.Println("This is a goroutine")
}()
  • goroutine 的创建成本很低,通常只需要几 KB 的栈空间(栈会根据需要动态增长)。
  • goroutine 的调度由 Go 运行时负责,开发者无需手动管理线程。

2. goroutine 的生命周期

goroutine 的生命周期从 go 语句开始,到以下情况之一结束:

  • 函数执行完毕。
  • 函数中调用了 return
  • 函数中发生了未被恢复的 panic。
  • 程序退出(主 goroutine 退出时,所有 goroutine 都会被强制终止)。

3. 管理 goroutine 的生命周期

由于 goroutine 是并发执行的,如果不加以管理,可能会导致以下问题:

  • 资源泄漏:goroutine 未正确退出,导致资源无法释放。
  • 数据竞争:多个 goroutine 同时访问共享资源,导致数据不一致。
  • 主 goroutine 提前退出:主 goroutine 退出后,其他 goroutine 会被强制终止,可能导致任务未完成。

以下是管理 goroutine 生命周期的常用方法:


3.1 使用 sync.WaitGroup 等待 goroutine 完成

sync.WaitGroup 是一种同步机制,用于等待一组 goroutine 完成任务。

package mainimport ("fmt""sync"
)func worker(id int, wg *sync.WaitGroup) {defer wg.Done() // 任务完成时调用 Donefmt.Printf("Worker %d starting\n", id)// 模拟任务fmt.Printf("Worker %d done\n", id)
}func main() {var wg sync.WaitGroupfor i := 1; i <= 3; i++ {wg.Add(1) // 增加计数器go worker(i, &wg)}wg.Wait() // 等待所有 goroutine 完成fmt.Println("All workers done")
}
  • wg.Add(1):增加计数器,表示启动一个 goroutine。
  • wg.Done():减少计数器,表示一个 goroutine 完成任务。
  • wg.Wait():阻塞主 goroutine,直到计数器归零。

3.2 使用 context 控制 goroutine 的取消

context 包提供了一种机制,用于在 goroutine 之间传递取消信号、超时和截止时间。

package mainimport ("context""fmt""time"
)func worker(ctx context.Context, id int) {for {select {case <-ctx.Done(): // 收到取消信号fmt.Printf("Worker %d canceled: %v\n", id, ctx.Err())returndefault:fmt.Printf("Worker %d is working\n", id)time.Sleep(500 * time.Millisecond)}}
}func main() {ctx, cancel := context.WithCancel(context.Background())for i := 1; i <= 3; i++ {go worker(ctx, i)}time.Sleep(2 * time.Second)cancel() // 取消所有 goroutinetime.Sleep(1 * time.Second) // 给 goroutine 一些时间退出fmt.Println("Main goroutine done")
}
  • context.WithCancel:创建一个可取消的 context。
  • ctx.Done():返回一个 channel,当 context 被取消时会关闭该 channel。
  • cancel():发送取消信号,通知所有监听该 context 的 goroutine 退出。

3.3 使用 channel 控制 goroutine 的退出

channel 是 goroutine 之间通信的主要方式,也可以用于控制 goroutine 的退出。

package mainimport ("fmt""time"
)func worker(stopChan chan bool) {for {select {case <-stopChan: // 收到退出信号fmt.Println("Worker exiting")returndefault:fmt.Println("Worker is working")time.Sleep(500 * time.Millisecond)}}
}func main() {stopChan := make(chan bool)go worker(stopChan)time.Sleep(2 * time.Second)stopChan <- true // 发送退出信号time.Sleep(1 * time.Second) // 给 goroutine 一些时间退出fmt.Println("Main goroutine done")
}
  • 通过 channel 发送退出信号,goroutine 监听该信号并退出。

3.4 避免 goroutine 泄漏

goroutine 泄漏是指 goroutine 无法退出,导致资源无法释放。以下是一些避免泄漏的建议:

  • 确保 goroutine 有明确的退出条件。
  • 使用 context 或 channel 控制 goroutine 的退出。
  • 避免在 goroutine 中无限循环,除非有明确的退出机制。

4. 主 goroutine 的管理

主 goroutine 是程序的入口,它的退出会导致整个程序退出。因此,主 goroutine 需要等待其他 goroutine 完成任务后再退出。

  • 使用 sync.WaitGroupcontext 确保主 goroutine 等待其他 goroutine 完成。
  • 避免在主 goroutine 中直接调用 os.Exit,这会导致其他 goroutine 被强制终止。

5. 总结

  • goroutine 的生命周期从创建开始,到任务完成或退出结束。
  • 使用 sync.WaitGroupcontext 或 channel 管理 goroutine 的生命周期。
  • 避免 goroutine 泄漏,确保 goroutine 有明确的退出条件。
  • 主 goroutine 需要等待其他 goroutine 完成任务后再退出。

通过合理管理 goroutine 的生命周期,可以编写出高效、可靠的并发程序。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/904716.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

安川HP165机器人R轴减速机维修故障解析

在现代工业自动化生产的广袤舞台上,工业机器人无疑是那颗最为璀璨的明星之一。而在众多知名品牌的工业机器人中,安川机器人以其卓越的性能和稳定的质量备受瞩目。然而,即使是如安川HP165这样的先进机器人,在长时间的运行过程中,也难免会出现一些故障问题,其中R轴减速机的…

ABB机器人平衡缸维修的深度剖析与实践

在现代工业自动化的舞台上,ABB机器人无疑是耀眼的明星,而3HAC026269 - 003型号更是以其卓越的性能和稳定性,广泛应用于各类生产线。然而,就像任何精密设备一样,ABB机器人也可能遭遇故障,其中平衡缸的问题尤为关键,直接关系到机器人的精准作业和整体效能,这就引出了ABB机…

Modbus RTU转TCP网关产品全面介绍

一、Modbus RTU 和 Modbus TCP 在多个方面存在差异 物理层与传输介质 Modbus RTU:常使用串口通信,如 RS - 232 或 RS - 485。RS - 232 适合短距离通信,通常在十几米以内;RS - 485 则支持更长距离,可达 1200 米左右,并且允许多个设备连接在同一总线上,适用于小型、局部的…

携手共筑金融数智生态新格局,长沙政企业务代表团莅临璞华科技考察交流

2025年3月,长沙市发展和改革委员会、长沙市委金融委员会办公室、长沙投资控股集团有限公司、长沙市长财科技有限公司等政企单位领导一行莅临璞华科技有限公司考察交流,双方围绕金融科技创新、技术研发合作等议题展开深度洽谈,达成初步合作意向。璞华科技CEO龚玉兴热烈欢迎考…

比较与排序类可视化图像

一、 柱状图(Bar Chart) 1.特点:柱状图通过柱子的高度或长度表示数据的大小,柱子可以是垂直的(柱状图)或水平的(条形图)。柱状图直观、易于理解,适合展示离散数据。 2.应用场景:比较不同类别的数据(如销售额、人口数量); 展示时间序列数据(如月度销售额)。…

《ESP32-S3使用指南—IDF版 V1.6》第十三章 UART实验

第十三章 UART实验 1)实验平台:正点原子DNESP32S3开发板 2)章节摘自【正点原子】ESP32-S3使用指南—IDF版 V1.6 3)购买链接:https://detail.tmall.com/item.htm?&id=768499342659 4)全套实验源码+手册+视频下载地址:http://www.openedv.com/docs/boards/esp32/ATK-…

AI与.NET技术实操系列(九):总结篇 ── 探讨.NET 开发 AI 生态:工具、库与未来趋势

1. 引言 本文作为本系列的最后一篇,旨在全面探讨 .NET 生态中与 AI 相关的工具、库、框架和资源,帮助开发者了解如何在 .NET 环境中开发 AI 应用。我们将分析 Microsoft 的 AI 战略、核心工具和库(如 ML.NET、Azure AI SDK 和 Semantic Kernel)、.NET 9 的新特性,以及社区…

windows 查询内存型号

1、通过任务管理器-性能 2、运行-cmd wmic memorychip get Speed,SMBIOSMemoryType根据返回的 SMBIOSMemoryType 值判断:24 表示 DDR3 26 表示 DDR4 34 表示 DDR5。‌2

更换数据库连接池失败

更换数据库连接池失败 将数据库连接池更换为druid,一直无法更换,保持默认的HiKari原因: 配置文件代码错误,在下图中,可以看见一个黄线的警告,这里出现了关键词错误.这个错误是导致出现配置失败的原因. 教训:配置文件的警告需要引起足够的重视.

SANA-Sprint:基于连续时间一致性蒸馏的单步扩散模型,0.1秒即可生成图像

扩散模型已成为现代文本到图像 (T2I) 生成技术的核心,能够生成高质量图像,但其迭代式推理过程导致生成速度缓慢。多数模型通常需要 20–50 个去噪步骤,这严重制约了其在实时应用中的部署。 现有的蒸馏技术旨在加速扩散模型的采样过程,然而,这些方法往往会引入稳定性问题,…

华为无线网络射频调优及WLAN跨VLAN的三层漫游示例

1.业务需求企业用户通过WLAN接入网络,以满足移动办公的最基本需求。 在覆盖区域内移动发生跨VLAN的漫游时,不影响用户的业务使用。2.组网需求AC组网方式:旁挂三层组网。DHCP部署方式:AC作为DHCP服务器为AP分配IP地址。 汇聚交换机SwitchB作为DHCP服务器为STA分配IP地址。业…

大型通用电子制造执行系统(MES)

​简介:系统参考西门子MOM智能制造Opcenter工业软件制造执行系统Camstar电子套件人机料法环数据建模业务对象和车间生产执行事务逻辑,采用面向对象分层设计与C#编程开发:包含电子制造企业人机料法环业务数据建模实体对象,数据实体持久化映射,数据工厂会话配置,车间生产服务…