Go-知识协程

Go-知识协程

  • 1. 基本概念
    • 1.1 进程
    • 1.2 线程
    • 1.3 协程
  • 2. 协程的优势
  • 3. 调度模型
    • 3.1 线程模型
    • 3.2 Go调度器模型
  • 4. 调度策略
    • 4.1 队列轮转
    • 4.2 系统调用
    • 4.3 工作量窃取
    • 4.4 抢占式调度
  • 5. GOMAXPROCS对性能的影响

一个小活动: https://developer.aliyun.com//topic/lingma/activities/202403?taskCode=14508&recordId=40dcecb786f9a65c2e83e95306822ce4#/?utm_content=m_fission_1 「通义灵码 · 体验 AI 编码,开 AI 盲盒」

githubio地址:https://a18792721831.github.io/

1. 基本概念

协程是Go语言最大的特色之一,也是将协程支持的非常优雅的实现,Go在语言层面直接提供对协程的支持。

1.1 进程

进程是应用程序的启动实例,每个进程都有独立的内存空间,不同进程通过进程间的通信方式来通信。

1.2 线程

线程从属于进程,每个进程至少包含一个线程,线程是CPU调度的基本单位,多个线程之间可以共享进程的资源并通过共享内存等线程间的通信方式来通信。

1.3 协程

协程可理解为一种轻量级的线程,与线程相比,协程不受操作系统调度,协程调度器由用户应用程序提供,协程调度器按照调度策略把协程调度到线程中运行。
Go应用程序的协程调度器由runtime包提供,用户使用go关键字即可创建协程,这也就是在语言层面直接支持协程的含义。

2. 协程的优势

在高并发应用中频繁创建线程会造成不必要的开销,所以有了线程池技术。在线程池中预先保存一定数量的线程,新任务将不再以创建线程的方式去执行,
而是将任务发布到任务队列中,线程池中的线程不断地从任务队列中取出任务并执行,这样可以有效地减少线程的创建和销毁带来的开销。
在这里插入图片描述

任务队列中的每一个任务成为G,而G往往代表一个函数。线程池中的worker线程不断地从任务队列中取出任务并执行,而worker现成则交给操作系统进行调度。
如果worker线程执行的G任务中发生系统调用,那么操作系统会将该线程置为阻塞状态,这也就意味着该线程在摸鱼儿,由于消费任务队列中的worker线程变少了,所以线程池消费任务的能力变弱了。
如果任务队列中的大部分任务都进行系统调用,则会让这中间状态恶化,大部分worker线程进入阻塞状态,从而任务队列中的任务产生堆积。
解决这个问题的一个思路就是重新审视线程池中线程的数量,增加线程池中的线程数量可以在一定程度上提高消费能力,但随着线程数量增多,过多线程争抢CPU资源,消费能力会有上限,甚至出现消费能力下降的现象。

一般服从正态分布。

过多的线程会导致上下文切换的开销变大,而工作在用户态的协程则能大大减小上下文切换的开销。协程调度器把可运行的协程逐个调度到线程中执行,
同时及时把阻塞的协程调度出线程,从而有效地避免了线程的频繁切换,达到使用少量线程实现高并发的效果。
多个协程分享操作系统分给线程的时间片,从而达到充分利用CPBU算力的目的,协程调度器则决定了协程运行的顺序。
在这里插入图片描述

3. 调度模型

3.1 线程模型

线程可分为用户线程和内核线程,用户线程由用户创建、同步和销毁,内核线程则由内核来管理。根据用户线程管理方式的不同,分为三种线程模型。

  • N:1 模型:N个用户线程运行在一个内核线程中,优点是用户线程上下文切换快,缺点是无法充分利用多核CPU的算力。
  • 1:1 模型:每个用户线程对应一个内核线程,优点是充分利用CPU的算力,缺点是线程上下文切换较慢。
  • M:N 模型:M个用户线程(协程)运行在N个线程中,优点是充分利用CPU的算力,并且上下文切换快;缺点是该模型的调度算法复杂。

Go语言使用的是M:N模型。

3.2 Go调度器模型

Go协程调度器模型中包含三个关键实体,machine(M),processor§和goroutine(G)。
在这里插入图片描述

  • M(machine): 工作线程,由操作系统调度。
  • P(processor): 处理器(Go定义的一个概念,不是指CPU),包含运行Go代码的必要资源,也有调度goroutine的能力。
  • G(goroutine): Go协程,每个go关键字都会创建一个协程。

M必须持有P才可以执行代码,和系统中的其他线程一样,M也会被系统调度阻塞。P的个数在程序启动时决定,默认情况下等于CPU的核数,可以使用环境变量GOMAXPROCS
或在程序中使用runtime.GOMAXPROCS()方法指定P的个数。
M的个数通常稍大于P的个数,因为除了运行Go代码,runtime包还有其他内置任务需要处理。
在这里插入图片描述

上图中包括两个工作线程M,每个M持有一个处理器P,并且每个M中有一个协程G在运行。其他的协程正在等待被调度,位于被称为runqueues的队列中。
每个处理器P中有一个runqueues队列,此外还有一个全局的runqueues队列,由多个处理器共享。
早期的调度器实现中(Go 1.1 之前)只包含全局的runqueues,多个处理器P通过互斥锁来调度队列中的协程,在多CPU或多核环境中,多个处理器需要经常争抢锁来调度全局队列中的协程,严重影响了并发执行效率。
后来引入了局部的runqueues,每个处理器P访问自己的runqueues时不需要加锁,大大提高了效率。
一般来说,处理器P中的协程G额外在创建的协程会加入本地的runqueues中,但如果本地的队列已满,或者阻塞的协程被唤醒,则协程会被放入全局的runqueues中,处理器P除了调度本地的runqueues中的协程,还会周期性地从全局runqueues中摘取协程来调度。

4. 调度策略

Go 协程调度器也是不断演进的,使得Go支持越来越多的调度策略,以便在不同的应用场景下都能产生优异的并发效果。

4.1 队列轮转

每个处理器P维护者一个协程G的队列,处理器P依次将协程G调度到M中执行。
协程G执行结束后,处理器P会再次调度一个协程G到M中执行。
同时,每个P会周期性地查看全局队列中是否有G待运行并将其调度到M中执行,全局队列中的G主要来自从系统调用中恢复的G。之所以P会周期性地查看全局队列,也是为了防止全局队列中的G长时间得不到调度机会而长时间等待。

4.2 系统调用

当线程在执行系统调用时,可能会被阻塞,对应到调度器模型,如果一个协程发起系统调度,那么对应的工作线程会被阻塞,这样依赖,处理器P的runqueues队列中的协程将得不到调度,相当于队列中的所有协程都被阻塞。
前面提到P的个数默认等于CPU的核数,每个M必须持有一个P才能执行G。一般情况下M的个数会略大于P的个数,多出来的M将会在G产生系统调用时发挥作用。与线程池类型,Go也有一个M的池子,需要时从池子中获取,用完放回池子,不够用就在创建一个。
在这里插入图片描述

当G0即将进入系统调用时,M0将释放P,进而M1获取P,继续执行P队列中剩下的G。M0由于陷入系统调用而被阻塞,M1接替M0的工作,只要P不空闲,就可以继续使用CPU。
在这里插入图片描述

冗余的M的来源有可能是缓存池,也有可能是新建的。当G0结束系统调用后,根据M0是否能获取到P,对G0进行不同的处理:

  • 如果有空闲的P,则获取一个P,继续执行G0
  • 如果没有空闲的P,则将G0放入全局队列,等待被其他的P调度。然后M0将进入到缓存池睡眠

4.3 工作量窃取

通过go关键字创建的协程通常会优先放到当前协程对应的处理器队列中,可能有些协程自身不断地派生新的协程,而有些协程不派生协程。这样的话,多个处理器P中维护的G队列有可能是不均衡的,如果不加以控制,则有可能出现部分处理器P非常繁忙,而部分处理器P空闲的情况。
为此,Go调度器提供了工作量窃取策略,即当某个处理器P没有需要调度的协程时,将从其他处理器中偷取协程。
在这里插入图片描述

上面的图中,右边的处理器P空闲,当全局队列中也没有协程需要调度,将从左边的处理器的runqueues中偷取一半的协程。
在这里插入图片描述

4.4 抢占式调度

抢占式调度,是指避免某个协程长时间执行,阻碍其他协程被调度。
调度器会监控每个协程的执行时间,一旦执行时间过长且有其他协程在等待执行时,会把写成暂停,转而调度等待的协程,已达到类似于时间片轮转的效果。
在Go 1.14 之前,Go 协程调度器抢占式调度机制有局限性,在设计中,是在函数调用间隙检查协程是否可被抢占,如果协程没有函数调用,则会无限期占用执行权:

package main

import (
    "fmt"
    "runtime"
    "time"
)

func main() {
   	// 设置只有一个处理器
	runtime.GOMAXPROCS(1)
	go func() {
		for {
			// 无函数调用的无限循环
		}
	}()
	// 系统调用,让出执行权
	time.Sleep(1 * time.Second)
	fmt.Println("xx")
}

运行超时了
在这里插入图片描述

如果在1.14和之后的Go中执行:
在这里插入图片描述

在Go 1.14 中,调度器引入了基于信号的抢占式机制,这个问题才解决了。

5. GOMAXPROCS对性能的影响

程序运行时就将GOMAXPROCS的大小设置为CPU的核数,可让Go程序充分利用CPU。在某些I/O密集型的应用中,这个值可能并不意味着性能最好。
理论上当某个goroutine进入系统调用时,会有一个新的M被启用或创建,继续占用CPU。但由于Go调度器检测到M被阻塞是有一定延迟的,即旧的M被阻塞和新的M得到运行之间是有一定时间间隔的,
所以在I/O密集型应用中可以把GOMAXPROCS的值设置的大一些,或许性能能好一些。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/508542.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【Go】十三、面向对象:方法

文章目录 1、面向对象2、结构体实例的创建3、结构体之间的转换4、方法5、结构体值拷贝6、方法的注意点7、方法和函数的区别8、跨包创建结构体实例 1、面向对象 Go的结构体struct ⇒ Java的Class类Go基于struct来实现OOP相比Java,Go去掉了方法重载、构造函数和析构函…

面向对象编程中的StringBuffer类详解

咦咦咦,各位小可爱,我是你们的好伙伴——bug菌,今天又来给大家普及Java SE相关知识点了,别躲起来啊,听我讲干货还不快点赞,赞多了我就有动力讲得更嗨啦!所以呀,养成先点赞后阅读的好…

vulhub中Apache solr XML 实体注入漏洞复现(CVE-2017-12629)

Apache Solr 是一个开源的搜索服务器。Solr 使用 Java 语言开发,主要基于 HTTP 和 Apache Lucene 实现。原理大致是文档通过Http利用XML加到一个搜索集合中。查询该集合也是通过 http收到一个XML/JSON响应来实现。此次7.1.0之前版本总共爆出两个漏洞:XML…

VSCode 设置vue2模板

点击设置 > 用户代码片段 > 输入Vue &#xff08;打开vue.json&#xff09;> 将代码复制内 "Print to console": {"prefix": "<","body": ["<template>"," <div class$1></div>"…

AI绘图cuda与stable diffusion安装部署始末与避坑

stable diffusion的安装说起来很讽刺&#xff0c;最难的不是stable diffusion&#xff0c;而是下载安装cuda。下来我就来分享一下我的安装过程&#xff0c;失败了好几次&#xff0c;几近放弃。 一、安装cuda 我们都知道cuda是显卡CPU工作的驱动&#xff08;或者安装官网的解释…

FPGA高端项目:解码索尼IMX327 MIPI相机+图像缩放+HDMI输出,提供开发板+工程源码+技术支持

目录 1、前言2、相关方案推荐本博主所有FPGA工程项目-->汇总目录我这里已有的 MIPI 编解码方案 3、本 MIPI CSI-RX IP 介绍4、个人 FPGA高端图像处理开发板简介5、详细设计方案设计原理框图IMX327 及其配置MIPI CSI RX图像 ISP 处理自研HLS图像缩放详解图像缓存HDMI输出工程…

3d在线虚拟数字展馆让学员通过游戏化体验接受爱国主义教育

随着科技的飞速发展&#xff0c;红色展厅已不再局限于实体空间。现在&#xff0c;借助VR虚拟仿真技术的强大力量&#xff0c;我们与多家党建馆推出一个全新的教育平台——VR红色虚拟展馆。在这里&#xff0c;爱国主题与尖端技术相结合&#xff0c;为广大学生提供一种全新的、互…

iPhone设备中如何分析和解决应用程序崩溃日志的问题

​ 目录 如何在iPhone设备中查看崩溃日志 摘要 引言 导致iPhone设备崩溃的主要原因是什么&#xff1f; 使用克魔助手查看iPhone设备中的崩溃日志 奔溃日志分析 总结 摘要 本文介绍了如何在iPhone设备中查看崩溃日志&#xff0c;以便调查崩溃的原因。我们将展示三种不同的…

目标检测——工业安全生产环境违规使用手机的识别

一、重要性及意义 首先&#xff0c;工业安全生产环境涉及到许多复杂的工艺和设备&#xff0c;这些设备和工艺往往需要高精度的操作和严格的监管。如果员工在生产过程中违规使用手机&#xff0c;不仅可能分散其注意力&#xff0c;降低工作效率&#xff0c;更可能因操作失误导致…

4-Linux实用操作

1. 各类小技巧&#xff08;快捷键&#xff09; 1.1 ctrl c 强制停止 Linux 某些程序的运行&#xff0c;如果想要强制停止它&#xff0c;可以使用快捷键 ctrl c 命令输入错误&#xff0c;也可以通过快捷键 ctrl c&#xff0c;退出当前输入&#xff0c;重新输入 1.2 ctrl …

【SQL Server】将数据导入导出到Excel表格当中

最开始&#xff0c;博主介绍一下自己的环境&#xff1a;SQL Sever 2008 R2 SQL Sever 大致都差不多 1. 通过自带软件的方式 首先找到下载SQL Sever中提供的导入导出工具 如果开始界面没有找到自己下载的路径 C:\Program Files\Microsoft SQL Server\100\DTS\Binn下的DTSWiz…

模型优化系列1:分类器CenterLoss使用Pytorch实现MNIST、CIFAR10、CIFAR100分类图示

CentLoss实现 前言 参考文章&#xff1a;史上最全MNIST系列&#xff08;三&#xff09;——Centerloss在MNIST上的Pytorch实现&#xff08;可视化&#xff09; 源码&#xff1a;Gitee或Github都有上传&#xff0c;保留了最优版&#xff0c;对最优版调整了一些参数看效果 Gitee…

运筹学经典问题(八):CVRP和VRP-TW

文章目录 问题描述问题建模决策变量数学建模基于容量的消除子环的约束 &#xff08;load-based SECs&#xff09; CVRP完整的数学模型加上时间窗限制的CVRP 问题描述 给定一个图&#xff0c;图上的点代表客户&#xff0c;边代表客户之间的路线&#xff0c;边的权重代表客户之间…

css-盒子阴影

1.box-shadow: 10px 20px 10px 10px blue; 参数对应顺序&#xff1a;上下&#xff0c;左右 &#xff0c;模糊程度&#xff0c;颜色 &#xff0c;阴影大小 2.box-shadow: 10px 20px 10px 20px blue,-10px -20px 10px 50px red; 负号就是相反方向 支持多个阴影 在后面加逗号 3…

128:忆往昔,迎春来

机缘 时间真的是过得好快啊&#xff0c;128&#xff0c;距离我的第一篇博客已经128天了&#xff0c;从大一上的冬天&#xff0c;到大一下的春夏&#xff0c;从一个初入大学的新人&#xff0c;到一个开始思考未来的新人。我开始不断更新博客&#xff0c;开始不断吸收知识&#…

OpenHarmony分布式五子棋-使用Canvas组件 实现棋盘、棋子的绘制

介绍 五子棋是一款比较流行的棋类游戏&#xff0c;此游戏使用分布式数据管理功能开发完成的。 本示例使用Canvas组件 实现棋盘、棋子的绘制&#xff0c;使用分布式数据管理 实现两台设备间数据的同步。 本示例使用分布式设备管理能力接口ohos.distributedDeviceManager。 分…

网络原理 - HTTP / HTTPS(1)——http请求

目录 一、认识HTTP协议 理解 应用层协议 二、fiddler的安装以及介绍 1、fiddler的安装 2、fiddler的介绍 三、HTTP 报文格式 1、http的请求 2、http的响应 五、认识URL 六、关于URL encode 一、认识HTTP协议 HTTP 全称为&#xff1a;“超文本传输协议”&#xff0c;是…

MySQL 连接池的实现

池化技术 池化技术能够减少资源对象的创建次数&#xff0c;提高程序的响应性能&#xff0c;特别是在高并发下这种提高更明显。共同特征 对象创建时间长。对象创建需要大量资源。对象创建后可被重复使用。 数据库连接池 数据库连接池&#xff08;Connection pooling&#xff…

【JAVA】postman import certificates in project 导入证书pfx

1. 打开这个按钮 2. File ->Settings 3. 打开“certificates”, Add certificates 添加证书 4. 输入证书地址&#xff0c;然后选择证书文件pfx , 输入证书密码。点击添加就可以了。 特别提醒&#xff1a; 推荐本地自己证书验证软件&#xff0c;“KeyStore” 这个软件可以…

SpringMVC --- 老杜

1、什么是SpringMVC&#xff1f; SpringMVC是一个基于Java实现了MVC设计模式的请求驱动类型的轻量级Web框架&#xff0c;通过把Model&#xff0c;View&#xff0c;Controller分离&#xff0c;将web层进行职责解耦&#xff0c;把复杂的web应用分成逻辑清晰的及部分&#xff0c;…