Go 语言并发编程基础:Goroutine 的创建与调度

简介: Go 语言的 Goroutine 是轻量级线程,由 runtime 管理,具有启动快、占用小、支持高并发的特点。本章介绍 Goroutine 的基本概念、创建方式(如使用 `go` 关键字或匿名函数)、M:N 调度模型及其工作流程,并探讨其在高并发场景中的应用,帮助理解其高效并发的优势。

 

Go 语言的并发模型是其最显著的语言特性之一。Goroutine 是 Go 实现并发的核心机制,它比线程更轻量,调度效率极高。

本章将带你了解 Goroutine 的基本概念、创建方式以及背后的调度机制。


一、什么是 Goroutine?

Goroutine 是由 Go 运行时(runtime)管理的轻量级线程。

特点:

  • • 启动快:创建成本远小于线程
  • • 占用小:初始栈大小仅约 2 KB,按需增长
  • • 数量多:支持成千上万个 Goroutine 并发运行
  • • 自动调度:由 Go runtime 自动调度到多个线程上执行

二、创建 Goroutine

创建一个 Goroutine 非常简单,只需使用 go 关键字:

func sayHello() {
    fmt.Println("Hello from Goroutine")
}
func main() {
    go sayHello() // 启动一个新的 Goroutine
    fmt.Println("Main function")
    time.Sleep(time.Second) // 等待子协程执行完毕
}

运行效果(输出可能顺序不定):

Main function
Hello from Goroutine

注意:主 Goroutine 退出时,程序将直接终止,其他 Goroutine 即使未完成也会被强制结束。


三、匿名函数启动 Goroutine

可以使用匿名函数快速创建 Goroutine:

go func(name string) {
    fmt.Println("Hello,", name)
}("Go")

四、Goroutine 的调度模型

Go 使用M:N 调度模型

  • M(Machine):操作系统线程(OS Thread)
  • G(Goroutine):用户级协程
  • P(Processor):逻辑处理器,调度器的核心

调度器作用:

  • • 把成千上万个 G 映射到有限的 M 上
  • • 利用 P 控制并发度(由 GOMAXPROCS 控制)

你可以通过设置 GOMAXPROCS 控制最大并发线程数:

runtime.GOMAXPROCS(2)

默认值为当前机器 CPU 核数。


五、调度器工作方式简要流程

  1. 1. 创建 Goroutine 后,进入可运行队列
  2. 2. 调度器从队列中取出 Goroutine 并分配给线程执行
  3. 3. 阻塞操作(如 IO)会让线程挂起并调度其他 Goroutine
  4. 4. 非抢占式调度 + 安全点机制(某些点才能切换)

六、调试与观察 Goroutine

可以使用 runtime 包查看当前 Goroutine 数量:

fmt.Println("Goroutine数量:", runtime.NumGoroutine())

使用 go tool pprof 或第三方工具(如 delve)分析 Goroutine 状态。


七、使用场景举例

  • • 高并发 Web 服务器处理请求
  • • 定时任务并发执行
  • • 异步日志写入
  • • 并发爬虫

八、小结

特性 说明
创建方式 使用 go 关键字
性能 数量轻量、栈空间动态增长
调度机制 M:N 多对多调度,由 runtime 管理
并发优势 快速、高效、代码简洁

 

相关文章
|
1月前
|
Go 开发者
Go 并发编程基础:无缓冲与有缓冲通道
本章深入探讨Go语言中通道(Channel)的两种类型:无缓冲通道与有缓冲通道。无缓冲通道要求发送和接收必须同步配对,适用于精确同步和信号通知;有缓冲通道通过内部队列实现异步通信,适合高吞吐量和生产者-消费者模型。文章通过示例对比两者的行为差异,并分析死锁风险及使用原则,帮助开发者根据场景选择合适的通道类型以实现高效并发编程。
|
3月前
|
SQL 监控 Go
新一代 Cron-Job分布式调度平台,v1.0.8版本发布,支持Go执行器SDK!
现代化的Cron-Job分布式任务调度平台,支持Go语言执行器SDK,多项核心优势优于其他调度平台。
77 8
|
7月前
|
并行计算 安全 Go
Go语言中的并发编程:掌握goroutines和channels####
本文深入探讨了Go语言中并发编程的核心概念——goroutine和channel。不同于传统的线程模型,Go通过轻量级的goroutine和通信机制channel,实现了高效的并发处理。我们将从基础概念开始,逐步深入到实际应用案例,揭示如何在Go语言中优雅地实现并发控制和数据同步。 ####
|
8月前
|
安全 Serverless Go
Go语言中的并发编程:深入理解与实践####
本文旨在为读者提供一个关于Go语言并发编程的全面指南。我们将从并发的基本概念讲起,逐步深入到Go语言特有的goroutine和channel机制,探讨它们如何简化多线程编程的复杂性。通过实例演示和代码分析,本文将揭示Go语言在处理并发任务时的优势,以及如何在实际项目中高效利用这些特性来提升性能和响应速度。无论你是Go语言的初学者还是有一定经验的开发者,本文都将为你提供有价值的见解和实用的技巧。 ####
|
8月前
|
算法 安全 程序员
Go语言的并发编程:深入理解与实践####
本文旨在探讨Go语言在并发编程方面的独特优势及其实现机制,通过实例解析关键概念如goroutine和channel,帮助开发者更高效地利用Go进行高性能软件开发。不同于传统的摘要概述,本文将以一个简短的故事开头,引出并发编程的重要性,随后详细阐述Go语言如何简化复杂并发任务的处理,最后通过实际案例展示其强大功能。 --- ###
|
8月前
|
安全 Go 数据处理
Go语言中的并发编程:掌握goroutine和channel的艺术####
本文深入探讨了Go语言在并发编程领域的核心概念——goroutine与channel。不同于传统的单线程执行模式,Go通过轻量级的goroutine实现了高效的并发处理,而channel作为goroutines之间通信的桥梁,确保了数据传递的安全性与高效性。文章首先简述了goroutine的基本特性及其创建方法,随后详细解析了channel的类型、操作以及它们如何协同工作以构建健壮的并发应用。此外,还介绍了select语句在多路复用中的应用,以及如何利用WaitGroup等待一组goroutine完成。最后,通过一个实际案例展示了如何在Go中设计并实现一个简单的并发程序,旨在帮助读者理解并掌
|
8月前
|
Go 调度 开发者
Go语言中的并发编程:深入理解goroutines和channels####
本文旨在探讨Go语言中并发编程的核心概念——goroutines和channels。通过分析它们的工作原理、使用场景以及最佳实践,帮助开发者更好地理解和运用这两种强大的工具来构建高效、可扩展的应用程序。文章还将涵盖一些常见的陷阱和解决方案,以确保在实际应用中能够避免潜在的问题。 ####
|
5月前
|
编译器 Go
揭秘 Go 语言中空结构体的强大用法
Go 语言中的空结构体 `struct{}` 不包含任何字段,不占用内存空间。它在实际编程中有多种典型用法:1) 结合 map 实现集合(set)类型;2) 与 channel 搭配用于信号通知;3) 申请超大容量的 Slice 和 Array 以节省内存;4) 作为接口实现时明确表示不关注值。此外,需要注意的是,空结构体作为字段时可能会因内存对齐原因占用额外空间。建议将空结构体放在外层结构体的第一个字段以优化内存使用。