golang学习笔记(协程的基础知识)

golang的协程

协程是一种轻量级的线程,它可以实现并发执行的并行操作。协程是Go语言中的一个核心特性,它使得程序能够以并发的方式运行,并且非常高效。与传统的线程相比,协程的创建和销毁成本非常低,可以方便地启动大量的协程来执行并行操作。

Golang的协程不同于其他语言中的线程或进程,它们是由Go语言的运行时系统调度的。协程的调度是基于协作式的,即协程自己主动让出CPU的控制权,而不是依赖于操作系统的调度器。

线程池的缺陷

在高并发应用中频繁创建线程会造成不必要的开销, 所以有了线程池。线程池中预先保存一定数量的线程, 而新任务将不再以创建线程的方式去执行, 而是将任务发布到任务队列, 线程池中的线程不断的从任务队列中取出任务并执行, 可以有效的减少线程创建和销毁所带来的开销。下图是一个简单的线程池的案例:
在这里插入图片描述
我们把任务队列中的每一个任务称作G, 而G往往代表一个函数。 线程池中的线程worker线程不断的从任务队列中取出任务并执行。 而worker线程的调度则交给操作系统进行调度。

如果worker线程执行的G任务中发生系统调用, 则操作系统会将该线程置为阻塞状态, 也意味着该线程在怠工, 也意味着消费任务队列的worker线程变少了, 也就是说线程池消费任务队列的能力变弱了。如果任务队列中的大部分任务都会进行系统调用, 则会让这种状态恶化, 大部分worker线程进入阻塞状态, 从而任务队列中的任务产生堆积。

解决这个问题的一个思路就是重新审视线程池中线程的数量, 增加线程池中线程数量可以一定程度上提高消费能力,但随着线程数量增多, 由于过多线程争抢CPU, 消费能力会有上限, 甚至出现消费能力下降。 如下图所示:
在这里插入图片描述

Goroutine调度器

线程数过多, 意味着操作系统会不断的切换线程, 频繁的上下文切换就成了性能瓶颈。 Go提供一种机制, 可以在线程中自己实现调度, 上下文切换更轻量, 从而达到了线程数少, 而并发数并不少的效果。 而线程中调度的就是Goroutine。
Goroutine主要概念

  • G( Goroutine) : 即Go协程, 每个go关键字都会创建一个协程。
  • M( Machine) : 工作线程,在Go中称为Machine。
  • P(Processor): 处理器( Go中定义的一个摡念, 不是指CPU) ,包含运行Go代码的必要资源, 也有调度goroutine的能力
    M必须拥有P才可以执行G中的代码, P含有一个包含多个G的队列, P可以调度G交由M执行。 其关系如下图所示:
    在这里插入图片描述

图中M是交给操作系统调度的线程, M持有一个P, P将G调度进M中执行。 P同时还维护着一个包含G的队列( 图中灰色部分) , 可以按照一定的策略将不能的G调度进M中执行。

P的个数在程序启动时决定, 默认情况下等同于CPU的核数, 由于M必须持有一个P才可以运行Go代码, 所以同时运行的M个数, 也即线程数一般等同于CPU的个数, 以达到尽可能的使用CPU而又不至于产生过多的线程切换开销。

Goroutine调度策略

队列轮转

上图中可见每个P维护着一个包含G的队列, 不考虑G进入系统调用或IO操作的情况下, P周期性的将G调度到M中执行,执行一小段时间, 将上下文保存下来, 然后将G放到队列尾部, 然后从队列中重新取出一个G进行调度。

除了每个P维护的G队列以外, 还有一个全局的队列, 每个P会周期性的查看全局队列中是否有G待运行并将其调度到M中执行, 全局队列中G的来源, 主要有从系统调用中恢复的G。 之所以P会周期性的查看全局队列, 也是为了防止全局队列中的G被饿死。

系统调用

上面说到P的个数默认等于CPU核数, 每个M必须持有一个P才可以执行G, 一般情况下M的个数会略大于P的个数, 这多出来的M将会在G产生系统调用时发挥作用。 类似线程池, Go也提供一个M的池子, 需要时从池子中获取, 用完放回池子, 不够用时就再创建一个。

当M运行的某个G产生系统调用时, 如下图所示:
在这里插入图片描述
如图所示, 当G0即将进入系统调用时, M0将释放P, 进而某个空闲的M1获取P, 继续执行P队列中剩下的G。 而M0由于陷入系统调用而进被阻塞, M1接替M0的工作, 只要P不空闲, 就可以保证充分利用CPU。

M1的来源有可能是M的缓存池, 也可能是新建的。 当G0系统调用结束后, 跟据M0是否能获取到P, 将会将G0做不同的处理:

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

工作量窃取

多个P中维护的G队列有可能是不均衡的, 比如下图:
在这里插入图片描述
竖线左侧中右边的P已经将G全部执行完, 然后去查询全局队列, 全局队列中也没有G, 而另一个M中除了正在运行的G外, 队列中还有3个G待运行。 此时, 空闲的P会将其他P中的G偷取一部分过来, 一般每次偷取一半。 偷取完如右图所示。

抢占式调度

goroutine设计之初为协作式调度,用户负责在各个goroutine之间协作式执行任务。协作式调度意味着希望协程自己会主动让出执行权,用户在加锁,读写通道时会主动让出执行权。

垃圾回收器是需要stop the world的。如果垃圾回收器想要运行了,那么它必须先通知其它的goroutine合作停下来,这会造成较长时间的等待时间。考虑一种很极端的情况,所有的goroutine都停下来了,只有其中一个没有停,那么垃圾回收就会一直等待着没有停的那一个。

抢占式调度可以解决这种问题,在抢占式情况下,如果一个goroutine运行时间过长,它就会被剥夺运行权。

Golang协程的用法

在Go语言中,要创建一个协程,只需在函数调用前加上关键字"go"。下面是一个简单的示例:

go 函数名()

这样就创建了一个新的协程,并在该协程中执行相应的函数。协程会与主线程并发执行,不会阻塞主线程的执行。

协程之间可以通过通道(Channel)进行通信。通道是一种在多个协程之间同步和传递数据的机制,它能够保证并发安全。通过通道,协程可以发送和接收数据,实现协程之间的协作。

package mainimport ("fmt""time"
)func longRunningTask() (res int) {time.Sleep(time.Second)for i := 0; i < 10; i++ {res += i}return res
}func main() {result := make(chan int)go func() {result <- longRunningTask()}()fmt.Println("Waiting for result...")fmt.Println("Result:", <-result)
}

在这里插入图片描述

参考文档

参考文档一

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

浏览器中不能使用ES6的扩展语法...报错

浏览器大多数已经支持ES6&#xff08;ECMAScript 2015&#xff09;的扩展语法&#xff08;...&#xff09;&#xff0c;包括Chrome、Firefox、Safari和Edge等。然而&#xff0c;如果你在某些浏览器中遇到无法使用扩展语法的问题&#xff0c;可能是由以下原因导致的&#xff1a;…

神经网络之防止过拟合

今天我们来看一下神经网络中防止模型过拟合的方法 在机器学习和深度学习中&#xff0c;过拟合是指模型在训练数据上表现得非常好&#xff0c;但在新的、未见过的数据上表现不佳的现象。这是因为模型过于复杂&#xff0c;以至于它学习了训练数据中的噪声和细节&#xff0c;而不…

一款开源高性能AI应用框架

前言 LobeChat 是一个基于 Next.js 框架构建的 AI 会话应用&#xff0c;旨在提供一个 AI 生产力平台&#xff0c;使用户能够与 AI 进行自然语言交互。 LobeChat应用架构 LobeChat 的整体架构由前端、EdgeRuntime API、Agents 市场、插件市场和独立插件组成。这些组件相互协作&a…

P8799 [蓝桥杯 2022 国 B] 齿轮

P8799 [蓝桥杯 2022 国 B] 齿轮 分析 最右边的齿轮的转速是最左边齿轮的q倍 最右边的齿轮的半径是最左边齿轮的q倍 题意即为&#xff1a;查询数组中是否存在两个数&#xff0c;其中一个是另一个的q倍 题目范围&#xff1a;查询次数q:2*10^5&#xff0c;数组范围2*10^5&…

XXL-JOB定时任务

1. xxl-job初识 1.1 xxl-job介绍 xxl-job 是大众点评大佬徐雪里开源的一款分布式任务调度框架&#xff0c;具有简单易用、轻量级、可扩展的特点。相比于Spring Task, Quartz&#xff0c;xxl-job有记录执行日志和运行大盘&#xff0c;方便开发人员和运维人员更好的管理任务。 …

如何进行面向对象分析、面向对象设计和面向对象编程

目录 1.引言 2.案例介绍和难点剖析 3.如何进行面向对象分析 4.如何进行面向对象设计 5.如何进行面向对象编程 6.总结 1.引言 面向对象分析(OOA)、面向对象设计(00D)和面向对象编程(OOP)是面向对象开发的3个主要环节。 在以往的工作中&#xff0c;作者发现&#xff0c;很多…

【JavaEE 初阶(一)】初识线程

❣博主主页: 33的博客❣ ▶️文章专栏分类:JavaEE◀️ &#x1f69a;我的代码仓库: 33的代码仓库&#x1f69a; &#x1faf5;&#x1faf5;&#x1faf5;关注我带你了解更多线程知识 目录 1.前言2.进程3.线程4.线程和进程的区别5.Thread创建线程5.1继承Thread创建线程5.2实现R…

专项技能训练五《云计算网络技术与应用》实训7-2:使用OpenDaylight界面下发流表

文章目录 使用OpenDaylight的web界面下发流表1. 根据前面实训教程&#xff0c;启动并登录到opendaylight的web控制页面&#xff0c;并使用mininet2. 单击左侧的“Nodes”查看节点信息。其中尤其需要关注Node Id&#xff0c;下发流表的时候会用到Node Id&#xff0c;如下图所示。…

无穷级数错题本

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 <

word中取消分页符或分段符前后的空格

在Word中&#xff0c;有时候&#xff0c;我们添加分页符后&#xff0c;从分页符后面的文字就全部掉到了下一页&#xff0c;那么如何避免呢&#xff1f; 选择word选项--高级&#xff0c;然后下滑到下面&#xff0c;将“取消分页符或分段符前后的空格”选中&#xff0c;如下图所…

解读简单的一段深度学习代码(已跑通)

最近一直想要学习深度学习的内容&#xff0c;想要复现大佬的代码&#xff0c;试了好多有的是不给数据&#xff0c;有的总是跑不通&#xff0c;这一个是已经跑通的一个代码&#xff0c;以上为证&#xff0c;学习最快的方式就是直接实战&#xff0c;大部分的内容都是比较偏向于理…

机器学习笔记导航(吴恩达版)

01.机器学习笔记01&#xff1a;机器学习前置概念导入、线性回归、梯度下降算法 02.机器学习笔记02&#xff1a;多元线性回归、多元梯度下降算法、特征缩放、均值归一化、正规方程 03.机器学习笔记03&#xff1a;octave安装、创建矩阵 04.机器学习笔记04&#xff1a;octave中移动…

LeetCode题练习与总结:分隔链表--86

一、题目描述 给你一个链表的头节点 head 和一个特定值 x &#xff0c;请你对链表进行分隔&#xff0c;使得所有 小于 x 的节点都出现在 大于或等于 x 的节点之前。 你应当 保留 两个分区中每个节点的初始相对位置。 示例 1&#xff1a; 输入&#xff1a;head [1,4,3,2,5,2]…

MyScaleDB:SQL+向量驱动大模型和大数据新范式

大模型和 AI 数据库双剑合璧&#xff0c;成为大模型降本增效&#xff0c;大数据真正智能的制胜法宝。 大模型&#xff08;LLM&#xff09;的浪潮已经涌动一年多了&#xff0c;尤其是以 GPT-4、Gemini-1.5、Claude-3 等为代表的模型你方唱罢我登场&#xff0c;成为当之无愧的风口…

第五十三节 Java设计模式 - 工厂模式

Java设计模式 - 工厂模式 工厂模式是一种创建模式&#xff0c;因为此模式提供了更好的方法来创建对象。 在工厂模式中&#xff0c;我们创建对象而不将创建逻辑暴露给客户端。 例子 在以下部分中&#xff0c;我们将展示如何使用工厂模式创建对象。 由工厂模式创建的对象将是…

因果推断 | 潜在结果框架的基础知识

文章目录 1 引言2 框架描述2.1 问题定义2.2 数学表达式 3 实现方案3.1 随机实验数据3.2 一般数据 4 方案评估5 总结6 相关阅读 1 引言 在上一篇文章&#xff08;运筹从业者也需要的因果推断入门&#xff1a;基础概念解析和体系化方法理解&#xff09;中&#xff0c;已经对因果…

Linux下Palabos源码编译安装及使用

目录 软件介绍 基本依赖 其它可选依赖 一、源码下载 二、解压缩&#xff08;通过方式1下载源码.zip格式&#xff09; 三、编译安装 3.1 自带算例 ​编辑3.2 自行开发算例 四、简单使用 4.1 串行运行 4.2 并行运行 4.3 查看结果 软件介绍 Palabos是一款基于LBM&…

EXCEL怎样把筛选后含有公式的数据,复制粘贴到同一行的其它列?

自excel2003版之后&#xff0c;常规情况下&#xff0c;复制筛选后的数据&#xff0c;会忽略隐藏行&#xff0c;仅复制其筛选后的数据&#xff0c;粘贴则是粘贴到连续单元格区域&#xff0c;不管行是在显示状态还是隐藏状态。 一、初始数据&#xff1a; 二、题主的复制粘贴问题…

windows驱动开发-内核调度(一)

驱动层面的调度和同步一向是内核中比较困难的部分&#xff0c;和应用层不一样&#xff0c;内核位于系统进程下&#xff0c;所以它的调度和同步一旦出现纰漏&#xff0c;那会影响所有的程序&#xff0c;而内核并不具备对于这种情况下的纠错能力&#xff0c;没有异常手段能够让挂…

植物生态化学计量主要理论和假说

1 功能关联假说 描述化学计量特征与植物生长功能的关联, 主要包括: (1) 生长速率假说(Growth Rate Hypothesis) (Sterner & Elser, 2002): 随生长速率增加, 植物N:P和C:P呈降低趋势, 而P 含量呈增加趋势。该假说有助于理解植物生长速率的调控机制, 但受其他因素调控…