当前位置:网站首页>go笔记之——goroutine
go笔记之——goroutine
2022-08-02 00:13:00 【Meme_xp】
goroutine底层实现原理!!!!!!!!!!!!!
概念
Goroutine可以理解为一种Go语言的协程(轻量级线程),是Go支持高并发的基础,属于用户态的线程,由Goruntime管理而不是操作系统。
底层数据结构存储了非常多的上下文:
底层数据结构:

最终是一个runtime.g对象放入了队列
状态流转:

状态轮转图

1.创建
通过go关键字调用底层函数runtime.newproc()创建一个goroutine当调用该函数之后goroutine会被设置成runnable状态
func main( ) {
go func() {
fmt.Println("func routine"")
}()
fmt.Println("main goroutine")
}
创建好的这个goroutine会新建一个自己的栈空间,同时在G的sched中维护栈地址与程序计数器这些信息。每个G在被创建之后,都会被优先放入到本地队列中,如果本地队列已经满了,就会被放入到全局队列中。
2.运行
goroutine本身只是一个数据结构,真正让goroutine运行起来的是调度器。Go实现了一个用户态的调度器(GMP模型),这个调度器充分利用现代计算机的多核特性,同时让多个goroutine运行,同时goroutine设计的很轻量级,调度和上下文切换的代价都比较小。

3.调度时机
调度时机
新起一个协程和协程执行完毕
会阻塞的系统调用,比如文件io、网络io. channel、mutex等阻塞操作
time.sleep
垃圾回收之后主动调用runtime.Gosched()·运行过久或系统调用过久等等
先本地g执行,执行完全局拿(每次全局拿记得上锁,防止被多次拿),全局拿玩就去其他本地队列偷,每次偷一半(下取整),如果没得偷的了就自旋,每次最多有设定好的个数自旋等待新的任务,防止cpu浪费资源
4.阻塞
channel的读写操作、等待锁、等待网络数据、系统调用等都有可能发生阻塞,会调用底层函
数runtime.gopark(),会让出CPU时间片,让调度器安排其它等待的任务运行,并在下次某个时候从该位置恢复执行。
当调用该函数之后,goroutine会被设置成waiting状态
5.唤醒
处于waiting状态的goroutine,在调用runtime.goready()函数之后会被唤醒,唤醒的goroutine会被重新放到M对应的上下文P对应的runqueue中,等待被调度。
当调用该函数之后,goroutine会被设置成runnable状态
6.退出
当goroutine执行完成后,会调用底层函数runtime.Goexit()。当调用该函数之后,goroutine会被设置成dead 状态
goroutine和线程的区别

goroutine泄露场景
泄漏原因
1.Goroutine内进行channel/mutex等读写操作被一直阻塞。
2.Goroutine内的业务逻辑进入死循环,资源一直无法释放。
3.Goroutine内的业务逻辑进入长时间等待,有不断新增的Goroutine进入等待
泄露场景
1.如果输出的goroutines数量是在不断增加的,就说明存在泄漏
2.nil channel,对空channel读写
3.channel如果忘记初始化,那么无论你是读,还是写操作,都会造成阻塞。
1.nil channel
func main() {
fmt.Println("before goroutines: ",runtime.NumGoroutine( ) )
block1()
time.Sleep(time.Second * 1)
fmt.Println("after goroutines: ", runtime.NumGoroutine()
}
func block1() {
var ch chan int
for i := 0; i < 10; i++ {
go func() {
<-ch3}()
}
}

2.接受不发送
channel发送数量草果channel接收数量,造成了阻塞
func block2() {
ch := make( chan int)
for i := 0; i < 10; i++ {
go func() {
ch <- 1}()
}
}
3.只接受不发送
channel接收数量超过了channelf发送的数量,也会造成阻塞
func block3( ) {
ch := make(chan int)
for i := 0; i < 10; i++ {
go func() {
<-ch}()
}
}
4.http request body未关闭
resp.Body.Close(),为被调用,groutine不会退出
5.互斥锁忘记解锁
第一个协程获取sync.Mutex加锁了,但是他可能在处理业务逻辑,又或是忘记Unlock 了。
因此导致后面的协程想加锁,却因锁未释放被阻塞了
func block5() {
var mutex sync.Mutex
for i := 0; i < 10; i++ {
go func() {
mutex.Lpck()}()
}
}
6.sync.WaitGroup原语使用不当
由于wg.Add的数量与wg.Done 数量并不匹配,因此在调用wg.wait方法后一直阻塞等待
func block6() {
var wg sync.waitGroup
for i := 0; i < 10; i++ {
go func() {
wg.Add(2)
wg.Done()
wg.wait()}()
}
}
如何排查
1.单个函数︰调用runtime.NumGoroutine方法来打印执行代码前后Goroutine的运行数量,进行前后比较,就能知道有没有泄露了。
2.生产/测试环境:使用PProf 实时监测Goroutine的数量
如何查看正在执行的goroutine的数量?
因为go服务一般是在线服务,所以我们引入pprof package
//在程序中引入pprof package
import _ "net/http/pprof"


如何控制并发的goroutine数量
为什么要控制goroutine并发的数量?
在开发过程中,如果不对goroutine加以控制而进行滥用的话,可能会导致服务整体崩溃。比如耗尽系统资源导致程序崩溃,或者CPU使用率过高导致系统忙不过来。
用什么方法控制goroutine并发的数量?
有缓冲channel利用缓冲满时发送阻塞的特性

有数据才创建!!!!!!!!!!!!这里最多支持三个goroutine
边栏推荐
- Industrial control network intrusion detection based on automatic optimization of hyperparameters
- 08-SDRAM: Summary
- [21-Day Learning Challenge] A small summary of sequential search and binary search
- 06-SDRAM : SDRAM control module
- uni-app项目总结
- Disk and file system management
- After an incomplete recovery, the control file has been created or restored, the database must be opened with RESETLOGS, interpreting RESETLOGS.
- IP核:FIFO
- Transient Stability Distributed Control of Power System with External Energy Storage
- Graphical LeetCode - 1161. Maximum Sum of In-Layer Elements (Difficulty: Moderate)
猜你喜欢

DFS详解

辨析内存函数memset、memcmp、memmove以及memcpy

Play NFT summer: this collection of tools is worth collecting

CVPR 2022 | SharpContour:一种基于轮廓变形 实现高效准确实例分割的边缘细化方法

Redis - message publish and subscribe

【解决】win10下emqx启动报错Unable to load emulator DLL、node.db_role = EMQX_NODE__DB_ROLE = core

Microsoft PC Manager V2.1 beta version officially released

Routing strategy

短视频seo搜索优化主要内容

poker question
随机推荐
Are test points the same as test cases?
632. 最小区间
What does the errorPage attribute of the JSP page directive do?
els block deformation
Using the "stack" fast computing -- reverse polish expression
els block deformation judgment.
Identify memory functions memset, memcmp, memmove, and memcpy
玩转NFT夏季:这份工具宝典值得收藏
回顾历史5次经济衰退时期:这一次可能会有何不同?
These 4 computer notepad software, you have to try
632. Minimum interval
短视频seo搜索优化主要内容
2022/08/01 Study Notes (day21) Generics and Enums
基于数据驱动的变电站巡检机器人自抗扰控制
Play NFT summer: this collection of tools is worth collecting
How does JSP use the page command to make the JSP file support Chinese encoding?
Realize deletion - a specified letter in a string, such as: the string "abcd", delete the "a" letter in it, the remaining "bcd", you can also pass multiple characters to be deleted, and pass "ab" can
JSP out. The write () method has what function?
06-SDRAM : SDRAM control module
扑克牌问题