Golang 语言控制并发 Goroutine的方法

作者:frank 时间:2024-02-14 21:18:19 

goroutine 是 Go语言中的轻量级线程实现,由 Go 运行时(runtime)管理。Go 程序会智能地将 goroutine 中的任务合理地分配给每个 CPU。

01介绍

Golang 语言的优势之一是天生支持并发,我们在 Golang 语言开发中,通常使用的并发控制方式主要有 Channel,WaitGroup 和 Context,本文我们主要介绍一下 Golang 语言中并发控制的这三种方式怎么使用?关于它们各自的详细介绍在之前的文章已经介绍过,感兴趣的读者朋友们可以按需翻阅。

02Channel

在 Golang 语言中,Channel 不仅可以用于协程之间通信,还可以使用 Channel 控制子协程,而且使用 Channel 实现并发控制比较简单,比如以下示例,我们在 Golang 应用程序中启动两个协程,分别是主协程和子协程,主协程需要等待子协程运行结束后再退出程序。

示例代码:


func main () {
done := make(chan struct{})
go func() {
 fmt.Println("goroutine run over")
 done <- struct{}{}
}()
<- done
fmt.Println("main goroutine run over")
}

阅读上面这段代码,我们在子 goroutine 运行结束后,通过 Channel 通知主 goroutine 退出程序,实际上也可以反过来处理,主 goroutine 通知子 goroutine 退出程序,主 goroutine 向 channel 中发送数据,子 goroutine 等待接收 channel 中的数据。

03sync.WaitGroup

如果在 Golang 应用程序中,需要让主 goroutine 等待多个 goroutine 都运行结束后再退出程序,我们应该怎么实现呢?是的,同样可以使用 Channel 实现,但是,有一个更优雅的实现方式,那就是 WaitGroup,顾名思义,WaitGroup 就是等待一组 goroutine 运行结束。

示例代码:


func main () {
wg := sync.WaitGroup{}
wg.Add(10)
for i := 0; i < 10; i++ {
 go func(id int) {
  fmt.Println(id, "运行结束")
  wg.Done()
 }(i)
}
wg.Wait()
fmt.Println("main goroutine run over")
}

阅读上面这段代码,我们启动 10 个子 goroutine,主 goroutine 需要等待 10 个子 goroutine 都运行结束后再退出程序,我们使用的是 WaitGroup,它有三个方法,分别是 Add、Done 和 Wait,实际上 WaitGroup 维护了一个计数器,这三个方法都是围绕这个计数器工作,Add 用于设置计数器的数值,Done 用于扣减计数器的数值,Wait 在计数器数值为 0 之前一直阻塞。关于 WaitGroup 的源码解读,在之前的文章中已介绍过,限于篇幅,这里就不再赘述。

04Context

Channel 和 WaitGroup 通常用于父子两个层级的 goroutine 的应用程序的并发控制中,如果在 Golang 应用程序中,子协程继续派生出协程,我们应该怎么控制呢?这种多级 goroutine 的应用程序,我们可以使用 Context 实现并发控制。

示例代码:


func main() {
ctx, cancel := context.WithCancel(context.Background())
go firstCtx(ctx)
time.Sleep(5 * time.Second)
fmt.Println("stop all sub goroutine")
cancel()
time.Sleep(5 * time.Second)
}

func firstCtx(ctx context.Context) {
go secondCtx(ctx)
for {
 select {
 case <-ctx.Done():
  fmt.Println("first done")
  return
 default:
  fmt.Println("first running")
  time.Sleep(2 * time.Second)
 }
}
}

func secondCtx(ctx context.Context) {
for {
 select {
 case <-ctx.Done():
  fmt.Println("second done")
  return
 default:
  fmt.Println("second running")
  time.Sleep(2 * time.Second)
 }
}
}

阅读上面这段代码,在子协程 firstCtx 启动子协程 secondCtx,主 goroutine 创建 context,并把 context 传递到所有子协程,然后主 goroutine 通过调用 cancle 停掉所有子协程。

05总结

本文我们介绍了不同场景中分别适合哪种控制并发 goroutine 的方式,其中,channel 适合控制少量 并发 goroutine,WaitGroup 适合控制一组并发 goroutine,而 context 适合控制多级并发 goroutine。

来源:http://developer.51cto.com/art/202106/668896.htm

标签:Golang,并发控制,Goroutine
0
投稿

猜你喜欢

  • javascript操作向表格中动态加载数据

    2024-04-27 15:21:09
  • c#中过滤html的正则表达式

    2023-07-04 04:03:24
  • JS鼠标3次点击事件实现代码及扩展思路

    2024-03-22 01:55:24
  • 重置mysql的root密码最简单的方法

    2024-01-18 22:30:02
  • NopCommerce架构分析之(八)多语言支持

    2024-05-13 09:15:53
  • Django基础之Model操作步骤(介绍)

    2022-04-12 12:17:50
  • python判断端口是否打开的实现代码

    2021-12-16 04:59:48
  • asp查询xml的代码实现无刷新 模糊查询

    2008-04-30 15:39:00
  • GO中的条件变量sync.Cond详解

    2024-02-10 15:08:35
  • python实现批量修改文件名

    2022-03-10 18:44:54
  • mysql 8.0.15 winx64压缩包安装配置方法图文教程

    2024-01-23 03:00:13
  • 基于Python中isfile函数和isdir函数使用详解

    2023-05-10 00:46:50
  • python中的列表与元组的使用

    2023-07-23 08:25:12
  • python石头剪刀布小游戏(三局两胜制)

    2021-07-24 00:06:30
  • 基于Django signals 信号作用及用法详解

    2021-08-01 10:59:52
  • python如何利用paramiko执行服务器命令

    2022-09-29 03:39:34
  • PHP实现图片合并的示例详解

    2023-06-08 14:14:07
  • python基础之模块的导入

    2023-10-24 05:44:11
  • Bootstrap风格的WPF样式

    2024-05-02 17:32:17
  • 如何利用python turtle绘图自定义画布背景颜色

    2021-08-02 17:28:49
  • asp之家 网络编程 m.aspxhome.com