您当前的位置:首页 > 电脑百科 > 程序开发 > 语言 > Go语言

Goroutine 开启和退出到底做了什么?

时间:2021-04-15 17:20:14  来源:Go语言中文网  作者:
Goroutine 开启和退出到底做了什么?

 

Illustration created for “A Journey With Go”, made from the original Go Gopher, created by Renee French.

ℹ️本文基于 Go 1.14。

在 Go 中,协程就是一个包含程序运行时的信息的结构体,如栈,程序计数器,或者它当前的 OS 线程。调度器还必须注意 Goroutine 的开始和退出,这两个阶段需要谨慎管理。

如果你想了解更多关于栈和程序计数器的信息,我推荐你阅读我的文章 Go:协程切换时涉及到哪些资源?[1]

开启

开启一个协程的处理过程相当简单。我们用一个程序作为例子:

Goroutine 开启和退出到底做了什么?

 

main 函数在打印信息之前开启了一个协程。由于协程会有自己的运行时间,因此 Go 通知运行时配置一个新协程,意味着:

  • 创建栈
  • 收集当前程序计数器或调用方数据的信息
  • 更新协程内部数据,如 ID 或 状态

然而,协程没有立即获取运行时状态。新创建的协程被加入到了本地队列的最前端,会在 Go 调度的下一周期运行。下面是现在这种状态的示意图:

Goroutine 开启和退出到底做了什么?

 

把协程放在队列的前端,这样它就会在当前协程运行之后第一个运行。如果有工作窃取发生,它不是在当前线程就是在另一个线程运行。

我推荐你阅读我的文章 Go: Go 调度器中的工作窃取[2]来获取更多信息。

在汇编指令中也可以看到协程的创建过程:

Goroutine 开启和退出到底做了什么?

 

协程被创建并被加入到本地协程队列后,它直接执行主函数的下一个指令。

退出

协程结束时,为了不浪费 CPU 资源,Go 必须调度另一个协程。这也使协程可以在以后复用。

在我的文章 Go: 协程怎么复用?[3]中你可以找到更多信息。

然而,Go 需要一个能识别到协程结束的方法。这个方法是在协程创建时控制的。创建协程时,Go 在将程序计数器设置为协程真实调用的函数之前,将堆栈设置为名为 goexit 的函数。这个技巧可以使协程在结束时必须调 goexit 函数。下面的程序可以使我们理解得更形象:

Goroutine 开启和退出到底做了什么?

 

根据输出信息进行堆栈追踪:

/path/to/src/main.go:16
/usr/local/go/src/runtime/asm_amd64.s:1373

用汇编写的 asm_amd64 文件包含这个函数:

Goroutine 开启和退出到底做了什么?

 

之后,Go 切换到 g0 调度另一个协程。

我们也可以调用 runtime.Goexit() 来手动终止协程:

Goroutine 开启和退出到底做了什么?

 

这个函数首先运行 defer 中的函数,然后会运行前面在协程退出时我们看到的那个函数。


via: https://medium.com/a-journey-with-go/go-how-does-a-goroutine-start-and-exit-2b3303890452

作者:Vincent Blanchon[4]译者:lxbwolf[5]校对:polaris1119[6]

本文由 GCTT[7] 原创编译,Go 中文网[8] 荣誉推出

参考资料

[1]

Go:协程切换时涉及到哪些资源?: https://medium.com/a-journey-with-go/go-what-does-a-goroutine-switch-actually-involve-394c202dddb7

[2]

Go: Go 调度器中的工作窃取: https://medium.com/a-journey-with-go/go-work-stealing-in-go-scheduler-d439231be64d

[3]

Go: 协程怎么复用?: https://medium.com/a-journey-with-go/go-how-does-go-recycle-goroutines-f047a79ab352

[4]

Vincent Blanchon: https://medium.com/@blanchon.vincent

[5]

lxbwolf: https://github.com/lxbwolf

[6]

polaris1119: https://github.com/polaris1119

[7]

GCTT: https://github.com/studygolang/GCTT

[8]

Go 中文网: https://studygolang.com/



Tags:Goroutine   点击:()  评论:()
声明:本站部分内容及图片来自互联网,转载是出于传递更多信息之目的,内容观点仅代表作者本人,如有任何标注错误或版权侵犯请与我们联系(Email:2595517585@qq.com),我们将及时更正、删除,谢谢。
▌相关推荐
Illustration created for “A Journey With Go”, made from the original Go Gopher, created by Renee French.ℹ️本文基于 Go 1.14。在 Go 中,协程就是一个包含程序运行...【详细内容】
2021-04-15  Tags: Goroutine  点击:(292)  评论:(0)  加入收藏
Go中,goroutine是否结束执行(退出)是由其自身决定,其他goroutine只能通过消息传递的方式通知其关闭,而并不能在外部强制结束一个正在执行的goroutine。当然有一种特殊情况会导致正在运行的goroutine会因为其他goroutine的...【详细内容】
2020-07-29  Tags: Goroutine  点击:(83)  评论:(0)  加入收藏
Go 中的并发性是以 goroutine(独立活动)和 channel(用于通信)的形式实现的。处理 goroutine 时,程序员需要小心翼翼地避免泄露。如果最终永远堵塞在 I/O 上(例如 channel 通信),或...【详细内容】
2019-09-26  Tags: Goroutine  点击:(164)  评论:(0)  加入收藏
▌简易百科推荐
zip 是一种常见的归档格式,本文讲解 Go 如何操作 zip。首先看看 zip 文件是如何工作的。以一个小文件为例:(类 Unix 系统下)$ cat hello.textHello!执行 zip 命令进行归档:$ zip...【详细内容】
2021-12-17  Go语言中文网    Tags:Go语言   点击:(12)  评论:(0)  加入收藏
大家好,我是 polarisxu。前段时间,Russ Cox 明确了泛型相关的事情,原计划在标准库中加入泛型相关的包,改放到 golang.org/x/exp 下。目前,Go 泛型的主要设计者 ianlancetaylor 完...【详细内容】
2021-11-30  Go语言中文网    Tags:slices 包   点击:(24)  评论:(0)  加入收藏
前言最近因为项目需要写了一段时间的 Go ,相对于 Java 来说语法简单同时又有着一些 Python 之类的语法糖,让人大呼”真香“。 但现阶段相对来说还是 Python 写的多一些,偶尔还...【详细内容】
2021-11-25  crossoverJie    Tags:Go   点击:(29)  评论:(0)  加入收藏
go-micro是基于 Go 语言用于开发的微服务的 RPC 框架,主要功能如下:服务发现,负载均衡 ,消息编码,请求/响应,Async Messaging,可插拔接口,最后这个功能牛p安装步骤安装proto...【详细内容】
2021-09-06    石老师小跟班  Tags:go-micro   点击:(196)  评论:(0)  加入收藏
GoLand 2021.2 EAP 5 现已发布。用户可以从工具箱应用程序中获得 EAP 构建,也可以从官方网站手动下载。并且从此 EAP 开始,只有拥有有效的 JetBrains 帐户才能加入该计划。手...【详细内容】
2021-06-29  IT实战联盟  今日头条  Tags:GoLand   点击:(185)  评论:(0)  加入收藏
作者:HDT3213今天给大家带来的开源项目是 Godis:一个用 Go 语言实现的 Redis 服务器。支持: 5 种数据结构(string、list、hash、set、sortedset) 自动过期(TTL) 发布订阅、地理位...【详细内容】
2021-06-18  HelloGitHub  今日头条  Tags:Go   点击:(125)  评论:(0)  加入收藏
统一规范篇合理规划目录本篇主要描述了公司内部同事都必须遵守的一些开发规矩,如统一开发空间,既使用统一的开发工具来保证代码最后的格式的统一,开发中对文件和代码长度的控制...【详细内容】
2021-05-18  1024课堂    Tags:Go语言   点击:(232)  评论:(0)  加入收藏
闭包概述 闭包不是Go语言独有的概念,在很多编程语言中都有闭包 闭包就是解决局部变量不能被外部访问的一种解决方案 是把函数当作返回值的一种应用 代码演示总体思想:在函数...【详细内容】
2021-05-14  HelloGo  今日头条  Tags:Go语言   点击:(223)  评论:(0)  加入收藏
一时想不开,想了解一下Go语言,于是安装了并体验了一下。下载1. 进入golang.google.cn 点击Download Go 2.选择对应的操作系统,点击后开始下载。 安装1. windows下执行傻瓜式安...【详细内容】
2021-05-12  程序员fearlazy  fearlazy  Tags:Go语言   点击:(236)  评论:(0)  加入收藏
1.简介channel是Go语言的一大特性,基于channel有很多值得探讨的问题,如 channel为什么是并发安全的? 同步通道和异步通道有啥区别? 通道为何会阻塞协程? 使用通道导致阻塞的协程...【详细内容】
2021-05-10  程序员麻辣烫  今日头条  Tags:Go通道   点击:(272)  评论:(0)  加入收藏
最新更新
栏目热门
栏目头条