【Go专家编程——协程】

1 协程的概念

1.1 基本概念

  • 进程是应用程序的启动实例,每个进程都有独立的内存空间,不同进程通过进程间的通信方式来通信
  • 线程从属于进程,每个进程至少包含一个线程,线程是CPU调度的基本单元,多个线程之间可以共享进程的资源并通过共享内存等线程间的通信方式来通信。
  • 协程可以理解为一种轻量级的线程,协程不受操作系统调度,协程调度器由用户应用程序提供,协程调度器按照调度策略把协程调度到线程中运行。

1.2 协程优势

在高并发应用中频繁创建线程会造成不必要的开销,所以由了线程池技术。使用的时候从中取出,使用完放回即可。
当线程在任务重发生系统调用时,会发生阻塞,则该线程会暂停执行任务。如果大量的线程都发生了系统调用,则会对系统发生阻塞,使任务得不到即使的处理。

  • 增加线程池中线程的数量在一定程度上可以提高处理能力
  • 但线程的增多,也会导致上下文切换的开销变大

那么当发生阻塞时,是否可以将当前任务放在一边,先执行其他任务呢?

  • 工作在用户态的协程可以减少上下文切换的开销
  • 通过协程调度器把可运行的协程逐个调度到线程中执行,同时及时把阻塞的协程调度出协程,从而有效避免了线程的频繁切换
  • 达到使用少量线程实现高并发的效果

2 调度模型

2.1 线程模型

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

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

2.2 Go调度器模型

Go协程调度模型中包含三个关键实体,machine(M),processor(P)和goroutine(简称G)

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

相关信息:

  • M必须持有P才可以执行代码
  • M也会被系统调用阻塞
  • P的个数在程序启动时决定,默认情况下等同于CPU的核数。但可以通过GOMAXPROCS这个环境变量指定

一个简单的调度器模型如下图所示:
在这里插入图片描述

  • 上图中包含2个工作线程M
  • 每个M持有一个P
  • 每个M中有一个协程在运行(已标记)
  • 其他背景的协程正在等待被调度,每个处理器P拥有宇哥runqueues队列
  • 此外还有一个全局的runqueues队列,由多个处理器共享

一般来说,处理器P中的协程G额外再创建的协程会被加入到本地的runqueues中;但如果本地的队列已满或阻塞的协程被唤醒,则会放入到全局的runqueues中;处理器除了调度本地的runqueues中的协程,还会周期性地从全局runqueues中摘取协程来调度。

3 调度策略

3.1 队列轮转

  • 每个处理器P维护者一个协程G的队列,处理器P依次将协程G调度到M中执行
  • 协程G执行结束后,处理器P会再次调度一个协程G到M中执行
  • 同时P会周期性查看全局变量中是否有待运行的G,并将其调度到M中运行
  • 全局变量中的G主要来自于系统调用中恢复的G
  • 周期性查看全局队列的目的是为了防止全局队列中的G长时间得不到调度机会而被“饿死”

3.2 系统调用

  • 协程发生系统调度时,对应的工作线程会被阻塞
  • 前面提到P的个数默认等于CPU的个数,每个M必须持有一个P才可以执行G
  • 一般情况下M个的个数会略大于P的个数。
  • 多出来的M将会在G发生系统调用时发生作用。
  • Go也提供了一个M的的池子,需要时从池子中获取,用完放回。不够时再创建。
    在这里插入图片描述
  • 当G0即将进入系统调用时
  • M0释放P
  • 冗余的M1获得P,继续执行P队列中剩下的G(冗余的M的来源可能是缓存池,也可能是新建的)
  • M0由于陷入系统调用而被阻塞,M1接替了M0的工作
  • 只要P不空闲,就可以充分利用CPU
  • 当G0结束系统调用后,根据能否获得P,对G0进行不同的处理
    • 如果有空闲的P,则获取一个P,继续执行G0
    • 如果没有空闲的P,则将G0放入全局队列,等待被其他P调度,然后M0将进入缓冲休眠

3.3 工作量窃取

说白了就是当前P已经将自己队列中的任务全部干完了,而全局队列中又没有新的G。于是从别人的队列中获取一半的工作量。

3.4 抢占式调度

所谓抢占式调度,是指避免某个协程长时间执行,而阻碍其他协程被调用的机制。

  • 调度器会监控每个协程执行的时间
  • 时间过长且有其他协程子在等待时
  • 会把协程暂停,转而调度等待的协程

3.5 GOMAXPROCS对性能的影响

一般来讲,程序运行时就将GOMAXPROCS的大小设置为CPU的核数,可让Go程序充分利用CPU。在某些I/O密集型的应用中,不妨把GOMAXPROCS的值设置得大一些,或许会有更好的效果。

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

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

相关文章

PCIe总线-事物层之TLP请求和完成报文格式介绍(六)

1.概述 TLP报文按照类型,可以大致分为4中类型,分别是IO请求报文、存储器请求报文、配置请求报文、完成报文和消息请求报文。IO请求报文可分为IO读请求(不携带数据)和IO写请求(携带数据)。存储器请求报文可…

架构师系列-定时任务解决方案

定时任务概述 在很多应用中我们都是需要执行一些定时任务的,比如定时发送短信,定时统计数据,在实际使用中我们使用什么定时任务框架来实现我们的业务,定时任务使用中会遇到哪些坑,如何最大化的提高定时任务的性能。 我…

Spark-RDD-依赖关系详解

Spark概述 Spark-RDD概述 Spark-RDD-依赖关系 在Apache Spark中,RDD(Resilient Distributed Dataset)是一种基本的抽象数据结构,代表了分布式的、不可变的数据集。 RDD之间的依赖关系在Spark中非常重要,因为它们决定了…

DBAPI怎么进行数据格式转换

DBAPI如何进行数据格式的转换 假设现在有个API,根据学生id查询学生信息,访问API查看数据格式如下 {"data":[{"name":"Michale","phone_number":null,"id":77,"age":55}],"msg"…

【java程序设计期末复习】chapter1 java入门

java入门 java的特点 (1)简单 Java要比C简单,C中许多容易混淆的概念,或者被Java弃之不用了,或者以一种更清楚更容易理解的方式实现 (2)面向对象 Java是面向对象的编程语言 (3&…

如何关闭或者减少屏蔽 CloudFlare 的真人检测

经常浏览境外网站的应该常碰到一个真人检测的提示(如下图所示)。最近,明月就收到了一个知乎上的付费咨询:问我如何去掉这个提示,由此明月也特别的研究了一下这个“真人检测”,这算是 CloudFlare 的一个特色了,基本上大家看到站点访问有这个提示的几乎都是用了 CloudFlar…

【同构字符串】python

思路: 先记录同一个值出现的次数,再将字典中的值取出,比较2个列表即可 代码: class Solution:def isIsomorphic(self, s: str, t: str) -> bool:dit1dict()dit2dict()for i in range(len(s)):if s[i] not in dit1:dit1[s[i…

01.并发编程简介

1 什么是并发编程 所谓并发编程是指在一台处理器上“同时”处理多个任务。并发是在同一实体上的多个事件。多个事件在同一时间间隔发生。 2 为什么我们要学习并发编程? 最直白的原因就是因为面试需要,大厂的 Java 岗的并发编程能力属于标配。 而在非大厂…

CentOS 7.9部署宝塔面板超详细

CentOS7 部署宝塔面板 Linux的宝塔面板搭建起来非常轻松,也可以用一句话来形容,如果喝水一样简单,只需一条命令剩下的交给时间,几分钟就能部署好,然后就可以直接进行登录,直接可以安装LNMP、LAMP平台&…

海外仓储管理系统:提升效率,标准化海外仓管理,科技赋能业务

海外仓作为跨境物流的关键一环,完全可以说海外仓的效率直接决定了后续物流的整体运作效率。 对于海外仓而言,一套高效,易用的海外仓储系统,无疑将成为提升企业竞争力的重要工具,帮助海外仓实现从野蛮生长到标准化管理…

2024.05.26 第 399 场周赛

Leetcode 第 399 场周赛 优质数对的总数 I Leetcode 优质数对的总数 I 给你两个整数数组 nums1 和 nums2&#xff0c;长度分别为 n 和 m。同时给你一个正整数 k。 如果 nums1[i] 可以被 nums2[j] * k 整除&#xff0c;则称数对 (i, j) 为 优质数对&#xff08;0 < i < n…

MT3040 矩形覆盖

代码&#xff1a; #include <bits/stdc.h> using namespace std; typedef long long ll; const int N 3e5 10; int n, ans, d, w; stack<int> s; // 单调栈 // 如果楼高度类似121&#xff08;凸&#xff0c;两边相等&#xff0c;中间比两边的大&#xff09;&…

微服务:Nacos简介以及安装部署

一、前言 Nacos&#xff08;全称Dynamic Naming and Configuration Service&#xff09;是一个由阿里巴巴集团开发并开源的分布式服务发现和配置管理平台。它是构建以“服务”为中心的现代应用架构&#xff08;如微服务范式、云原生范式&#xff09;的服务基础设施。 Nacos架构…

设计模式深度解析:分布式与中心化,IT界两大巨头“华山论剑”

​&#x1f308; 个人主页&#xff1a;danci_ &#x1f525; 系列专栏&#xff1a;《设计模式》《MYSQL应用》 &#x1f4aa;&#x1f3fb; 制定明确可量化的目标&#xff0c;坚持默默的做事。 ✨IT界的两大巨头交锋✨ &#x1f44b; 在IT界的广阔天地中&#xff0c;有两座…

微火问答:全域外卖和本地生活服务是同个项目吗?

当前&#xff0c;本地生活赛道火爆程度不断升级&#xff0c;作为其主要板块之一的团购外卖也持续迸发出新的活力。而全域运营的出现无疑是给团购外卖这把正在熊熊燃烧的烈火&#xff0c;又添了一把新柴&#xff01; 所谓全域运营&#xff0c;简单来说&#xff0c;就是指所有领…

数据安全不容小觑:.hmallox勒索病毒的防范与应对

一、引言 随着网络技术的飞速发展&#xff0c;网络安全问题日益凸显&#xff0c;其中勒索病毒作为一种极具破坏性的网络攻击手段&#xff0c;已在全球范围内造成了巨大的经济损失和社会影响。在众多勒索病毒中&#xff0c;.hmallox勒索病毒以其狡猾的传播方式和强大的加密能力…

linux 常用命令:find grep ps netstat sudo df du rm

rm 命令 删除 -r 是递归参数&#xff08;recursive&#xff09;&#xff0c;用于删除目录及其内容。如果不加这个参数&#xff0c;rm 命令无法删除非空目录。-f 是强制参数&#xff08;force&#xff09;&#xff0c;用于强制删除文件或目录&#xff0c;不会进行任何确认提示…

g-h Filter 详细讲解

g-h 过滤器 g-h 滤波器百科介绍。 之前的翻译大家&#xff0c;我看都没什么阅读量&#xff0c;可能大家都不是很想看&#xff08;估计也是我英文太水&#xff09;。那么这篇博客我就先暂停直接翻译原文&#xff0c;而是直接说一下自己的理解。 本文章背后的书的详细介绍可以…

企业客户信息反馈|基于SprinBoot+vue的企业客户信息反馈平台(源码+数据库+文档)

企业客户信息反馈平台 目录 基于SprinBootvue的企业客户信息反馈平台 一、前言 二、系统设计 三、系统功能设计 1平台功能模块 2后台登录 5.2.1管理员功能 5.2.2客户功能 四、数据库设计 五、核心代码 六、论文参考 七、最新计算机毕设选题推荐 八、源码获取&am…

vscode远程连接Ubuntu mysql服务器

注意&#xff1a;刚开始使用root用户死活连接不上&#xff0c;可能就是root用户没有权限的问题&#xff0c;可以尝试创建一个新的数据库用户&#xff0c;授予权限进行连接 ubuntu安装mysql 创建新用户 执行&#xff1a;sudo apt-get install mysql-server安装服务器(yum) 执…