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.rhkb.cn/news/318856.html

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

相关文章

k8s 资源组版本支持列表

1 kubernetes的资源注册表 kube-apiserver组件启动后的第一件事情是将Kubernetes所支持的资源注册到Scheme资源注册表中,这样后面启动的逻辑才能够从Scheme资源注册表中拿到资源信息并启动和运行API服务。 kube-apiserver资源注册分为两步:第1步,初始化Scheme资源注册表;…

thinkphp家政上门预约服务小程序家政保洁师傅上门服务小程序上门服务在线派单安装教程

介绍 thinkphp家政上门预约服务小程序家政保洁师傅上门服务小程序上门服务在线派单安装教程 上门预约服务派单小程序家政小程序同城预约开源代码独立版安装教程 程序完整&#xff0c;经过安装检测&#xff0c;可放心下载安装。 适合本地的一款上门预约服务小程序&#xff0…

数据结构------栈的介绍和实现

目录 1.栈的一些初步认识 2.栈的实现 3.相关的函数介绍 &#xff08;1&#xff09;栈的初始化 &#xff08;2&#xff09;栈的销毁 &#xff08;3&#xff09;栈的数据插入 &#xff08;6&#xff09;判断是否为空 &#xff08;7&#xff09;栈的大小 4.栈的实现完整…

iBarcoder for Mac:一站式条形码生成软件

在数字化时代&#xff0c;条形码的应用越来越广泛。iBarcoder for Mac作为一款专业的条形码生成软件&#xff0c;为用户提供了一站式的解决方案。无论是零售、出版还是物流等行业&#xff0c;iBarcoder都能轻松应对&#xff0c;助力用户实现高效管理。 iBarcoder for Mac v3.14…

win11 Terminal 部分窗口美化

需求及分析&#xff1a;因为在 cmd、anaconda prompt 窗口中输入命令较多&#xff0c;而命令输入行和输出结果都是同一个颜色&#xff0c;不易阅读&#xff0c;故将需求定性为「美化窗口」。 美化结束后&#xff0c;我在想是否能不安装任何软件&#xff0c;简单地通过调整主题颜…

windows驱动开发-PNP管理器

PNP技术是由Microsoft提出的&#xff0c;英文Plug and play的缩写&#xff0c;中译即插即用&#xff0c;意思是系统自动侦测周边设备和板卡并自动安装设备驱动程序&#xff0c;做到插上就能用&#xff0c;无须人工干预&#xff0c;是Windows自带的一项技术。所谓即插即用是指将…

从零开始搭建一个vue项目

从零开始搭建一个vue项目 一、环境准备 1.1 安装node.js 选择合适的LTS版本&#xff0c;然后下载安装&#xff0c;安装地址&#xff1a;https://nodejs.org/en/download 在命令行中查看已安装的node.js版本 node -v v14.14.01.2 切换为淘宝的镜像源 解决国内下载慢的问题,…

极简shell制作

&#x1f30e;自定义简单shell制作 &#xff08;ps: 文末有完整代码&#xff09; 文章目录&#xff1a; 自定义简单shell制作 简单配置Linux文件 自定义Shell编写 命令行解释器       获取输入的命令       字符串分割       子进程进行进程替换 内建命令…

.NET 检测地址/主机/域名是否正常

&#x1f331;PING 地址/主机名/域名 /// <summary>/// PING/// </summary>/// <param name"ip">ip</param>/// <returns></returns>public static bool PingIp(string ip){System.Net.NetworkInformation.Ping p new System.N…

OpenAI 新推出 AI 问答搜索引擎——SearchGPT 震撼登场

您的浏览器不支持 video 标签。 OpenAI-SearchGPT 近日&#xff0c;OpenAI 曝光了自己的一款令人瞩目的 AI 问答搜索引擎——SearchGPT。这款搜索引擎带来了全新的搜索体验&#xff0c;给整个行业带来了巨大的压力。 SearchGPT 支持多种强大的功能。首先&#xff0c;它能够通过…

蓝桥杯练习系统(算法训练)ALGO-949 勇士和地雷阵

资源限制 内存限制&#xff1a;256.0MB C/C时间限制&#xff1a;1.0s Java时间限制&#xff1a;3.0s Python时间限制&#xff1a;5.0s 问题描述 勇士们不小心进入了敌人的地雷阵&#xff08;用n行n列的矩阵表示&#xff0c;*表示某个位置埋有地雷&#xff0c;-表示某个…

ARP防火墙能够为网络安全贡献什么样的力量

ARP防火墙&#xff08;Address Resolution Protocol Firewall&#xff09;作为网络安全的一环&#xff0c;起到保护网络免受ARP欺骗攻击的关键作用。今天德迅云安全给您介绍ARP防火墙的相关方面&#xff0c;帮助您深入了解和认识这一关键的安全措施。 网络安全对于现代社会的信…

金三银四面试题(二十四):享元模式知多少?

什么是享元模式 享元模式&#xff08;Flyweight Pattern&#xff09;是一种结构型设计模式&#xff0c;旨在通过共享对象来减少内存使用&#xff0c;从而提高性能。它主要用于处理大量细粒度对象的情况&#xff0c;通过将这些对象的可共享部分&#xff08;内部状态&#xff09…

毫米波雷达原理(含代码)(含ARS548 4D毫米波雷达数据demo和可视化视频)

毫米波雷达原理 1. 传统毫米波雷达1.1 雷达工作原理1.2 单目标距离估计1.3 单目标速度估计1.4 单目标角度估计1.5 多目标距离估计1.6 多目标速度估计1.7多目标角度估计1.7 总结 3. FMCW雷达数据处理算法4. 毫米波雷达的目标解析(含python代码)5. ARS548 4D毫米波雷达数据demo(含…

MYSQL从入门到精通(二)

1、MYSQL高级概述 【1】架构概述 【2】索引优化 【3】查询截取 【4】mysql锁机制 【5】主从复制 2、MYSQL概述 【1】mysql内核 【2】sql优化工程师 【3】mysql服务器的优化 【4】各种参数常量设定 【5】查询语句优化 【6】主从复制 【7】软硬件升级 【8】容灾百分 【9】sql编…

Flutter笔记:Widgets Easier组件库(1)使用各式边框

Flutter笔记 Widgets Easier组件库&#xff08;1&#xff09;&#xff1a;使用边框 - 文章信息 - Author: 李俊才 (jcLee95) Visit me at CSDN: https://jclee95.blog.csdn.netMy WebSite&#xff1a;http://thispage.tech/Email: 291148484163.com. Shenzhen ChinaAddress o…

Leetcode—377. 组合总和 Ⅳ【中等】

2024每日刷题&#xff08;124&#xff09; Leetcode—377. 组合总和 Ⅳ 算法思想 实现代码 class Solution { public:int combinationSum4(vector<int>& nums, int target) {vector<unsigned long long>dp(target 1);dp[0] 1;for(int i 1; i < target;…

React、React Router 和 Redux 常用Hooks 总结,提升您的开发效率!

Hooks 是 React 16.8 中引入的一种新特性&#xff0c;它使得函数组件可以使用 state 和其他 React 特性&#xff0c;从而大大提高了函数组件的灵活性和功能性。下面分别总结React、React Router 、Redux中常用的Hooks。 常用Hooks速记 React Hooks useState&#xff1a;用于…

社交媒体数据恢复:WorldTalk

WorldTalk数据恢复方法 在本文中&#xff0c;我们将探讨如何恢复在WorldTalk中删除的信息。请注意&#xff0c;这些步骤并不是专门针对WorldTalk软件设计的&#xff0c;而是基于一般的手机数据恢复流程。由于WorldTalk是一款全球5亿人使用的交友APP&#xff0c;用户分别来自中…

EDA(一)Verilog

EDA&#xff08;一&#xff09;Verilog Verilog是一种用于电子系统设计自动化&#xff08;EDA&#xff09;的硬件描述语言&#xff08;HDL&#xff09;&#xff0c;主要用于设计和模拟电子系统&#xff0c;特别是在集成电路&#xff08;IC&#xff09;和印刷电路板&#xff08;…