欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 汽车 > 时评 > 15分钟学 Go 第 23 天:并发基础:Goroutines

15分钟学 Go 第 23 天:并发基础:Goroutines

2025/2/11 16:23:07 来源:https://blog.csdn.net/weixin_40780178/article/details/143264236  浏览:    关键词:15分钟学 Go 第 23 天:并发基础:Goroutines

第23天:并发基础:Goroutines

欢迎来到Go语言学习的第23天!今天我们将深入探讨Goroutines的概念,这是Go语言并发编程的核心要素。理解Goroutines的工作原理和使用方法,将使你能够编写高效的并发应用程序。

1. 并发和并行的概念

在深入Goroutines之前,我们需要清楚理解并发并行的区别:

  • 并发(Concurrency)是指多个任务在同一时间段内进行调度,但并不一定同时执行。
  • 并行(Parallelism)则是指多个任务在同一时刻真正同时执行。

Go语言的并发机制主要通过Goroutines实现。

1.1 Goroutines与传统线程的对比

特性Goroutines传统线程
创建开销轻量级,创建简单开销较大,创建复杂
管理由Go运行时(Go runtime)管理需要操作系统调度
内存占用每个Goroutine占用约2KB每个线程占用更多内存
数量可以同时运行数万个Goroutines受限于操作系统,通常为数百个

2. 什么是Goroutines

Goroutines是Go语言提供的轻量级线程,用于并发执行。Goroutines的创建和调度非常高效,因此开发人员可以创建成千上万的Goroutines。

2.1 创建Goroutine

在Go中,通过使用 go 关键字来创建一个Goroutine。例如:

go func() {fmt.Println("Hello from Goroutine")
}()

上面的代码创建了一个新的Goroutine,运行一个匿名函数。

3. 设置Goroutines示例

接下来,我们来看一个使用Goroutines的简单示例,其中我们将启动多个Goroutines来并发执行任务。

3.1 示例代码

package mainimport ("fmt""time"
)func printNumbers(from, to int) {for i := from; i <= to; i++ {fmt.Println(i)time.Sleep(100 * time.Millisecond) // 模拟耗时操作}
}func main() {fmt.Println("Starting Goroutines")go printNumbers(1, 5) // 启动第一条Goroutinego printNumbers(6, 10) // 启动第二条Goroutine// 主Goroutine等待输入,以保持程序运行var input stringfmt.Scanln(&input)
}

3.2 代码说明

  • printNumbers 函数:打印从 fromto 的数字,并在每次打印后暂停100毫秒,模拟一些耗时操作。
  • main 函数
    • 使用 go 关键字启动两个Goroutines,分别打印1到5和6到10的数字。
    • 主Goroutine使用 fmt.Scanln 保持运行,直到有用户输入,以便等待Goroutines完成。

3.3 代码运行流程图

下面是代码执行流程的示意图:

+---------------------+
|      main()        | 
+---------------------+
| Start Goroutine 1  |
| start printNumbers(1,5) |
+---------------------+
| Start Goroutine 2  |
| start printNumbers(6,10) |
+---------------------+
| Wait for user input |
+---------------------+|v
+---------------------+
|  printNumbers(1,5)  |
|                      |
+---------------------+
|  printNumbers(6,10) |
|                      |
+---------------------+

3.4 运行示例

在项目目录下运行该程序:

go run main.go

你应该能够看到1到10的数字交替打印,表示两个Goroutines正并发执行。

4. Goroutines的调度

Goroutines的调度是由Go的运行时系统自动管理的。它会在适当的时候将Goroutines从一个操作系统线程切换到另一个线程,确保尽可能高效地利用CPU资源。

4.1 Go调度器

Go调度器基于M:N调度模型,其中M是操作系统线程的数量,N是Goroutines的数量。Go会根据需要在有限的线程资源中调度多个Goroutines。

5. Goroutines的特性

5.1 Goroutines是非阻塞的

Goroutines是非阻塞的,即当一个Goroutine在执行某个操作时,其他Goroutines仍然可以继续执行。

5.2 Goroutines的生命周期

  • Goroutines开始时由 go 关键字触发。
  • 当Goroutine退出时(执行完毕或发生错误),其资源会被自动释放。

6. 管理Goroutines

在有些情况下,我们需要控制Goroutines的数量,或等待它们完成。常用的方法有使用WaitGroup与Channel。

6.1 使用WaitGroup

示例代码

package mainimport ("fmt""sync""time"
)func printNumbers(from, to int, wg *sync.WaitGroup) {defer wg.Done() // 在函数结束时调用Donefor i := from; i <= to; i++ {fmt.Println(i)time.Sleep(100 * time.Millisecond)}
}func main() {var wg sync.WaitGroupfmt.Println("Starting Goroutines")wg.Add(2) // 添加2个Goroutinego printNumbers(1, 5, &wg)go printNumbers(6, 10, &wg)wg.Wait() // 等待所有Goroutines完成fmt.Println("All Goroutines completed")
}

6.2 代码说明

  • 使用 sync.WaitGroup 来管理多个Goroutines的执行。
  • 在每个Goroutine中,调用 wg.Done() 表示完成该Goroutine的任务。
  • 在主Goroutine中,调用 wg.Wait() 来等待所有的Goroutines完成。

6.3 运行输出

你可以运行这个示例并观察输出,程序将在所有Goroutines完成后打印“所有Goroutines完成”。

7. 使用Channel与Goroutines

Channel是Go语言中用于在Goroutines之间通信的同步原语。通过Channel,你可以在多个Goroutines之间安全地传递数据。

7.1 基本用法

示例代码

package mainimport ("fmt""time"
)func printNumbers(ch chan int) {for i := 1; i <= 5; i++ {time.Sleep(100 * time.Millisecond)ch <- i // 发送数据到Channel}close(ch) // 关闭Channel
}func main() {ch := make(chan int) // 创建Channelgo printNumbers(ch) // 启动Goroutine// 从Channel读取数据for num := range ch {fmt.Println(num)}fmt.Println("All numbers printed")
}

7.2 代码说明

  • printNumbers 函数向 Channel 中发送1到5之间的数字,并最终关闭Channel。
  • 主Goroutine从Channel中读取数据,直到Channel关闭。

7.3 代码运行流程图

+---------------------+
|      main()        | 
+---------------------+
| Create Channel      |
+---------------------+
| Start Goroutine     |
| printNumbers(ch)    |
+---------------------+|v
+---------------------+
|  printNumbers       |
|                     |
|  Send numbers to    |
|  Channel            |
+---------------------+|v
+---------------------+
|   Read from Channel  |
|   Print numbers      |
+---------------------+

8. 总结与练习

在今天的学习中,我们深入理解了Goroutines的概念及其重要性。Goroutines允许我们轻松编写并发程序,而无需涉及复杂的线程管理。

练习

  1. 创建一个程序,启动多个Goroutines,并以随机顺序打印字母A到Z。
  2. 使用Channel实现一个Goroutine生产者-消费者模型,生产者生成数字,消费者打印数字。

怎么样今天的内容还满意吗?再次感谢观众老爷的观看,关注GZH:凡人的AI工具箱,回复666,送您价值199的AI大礼包。最后,祝您早日实现财务自由,还请给个赞,谢谢!

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com