Go学习笔记 -- 并发原理
admin
2024-01-17 23:56:29
0

文章目录

    • Go 协程和普通线程对比
      • 内核级线程(线程)
        • 线程优点
        • 线程缺点
      • 用户级线程(协程)
        • 协程优点
        • 协程缺点
    • 调度器(GPM)
      • G\P\M 之间的工作关系
    • Go 使用协程
      • 创建协程
      • 注意

Go 协程和普通线程对比

       Go 拥有极强的并发编程能力,而 Go 并发编程强势原因,一部分原因是因为语法简单 ,还有一个更核心的原因是 Go 中协程 goroutine (用户态线程)的存在。
       在 Gogoroutine 是比普通线程(内核态线程)更加轻量化的存在。

内核级线程(线程)

       内核态线程简称线程,是在内核中维护了线程表进行跟踪监控的线程。是 CPU 调度和分派的基本单位,是具备进程某些属性,能够独立运行的更小单位,所以也称为轻量级进程。

       如果使用内核态线程在一个 CPU 上实现任务的并发,那么 CPU 会通过分配时间片的方式去执行任务,当正在运行的任务所分配的时间片用完了,就会切换到另一个任务,而在切换的之前会保存当前任务的状态(CPU寄存器、程序计数器中的内容),当下次再次切换到这个任务之前就会先加载之前保存到任务状态,这个过程称作上下文切换。

       而在上下文切换的过程该线程会从用户态转为内核态,加载时再由内核态转为用户态。而用户态和内核态切换的代价是很高的,从用户态到内核态的切换比较耗费资源的,而且内核资源是很珍贵的,所以内核态线程过多时,可能会出现内核资源耗尽的情况。

线程优点

  1. 多核 CPU 利用 :内核具有0级权限,因此可以在多个 CPU 上执行内核线程
  2. 操作系统级优化:线程之间是相对独立的,一个线程阻塞不会影响其他线程的执行。内核态线程在进行你 IO 操作时不需要进行系统调用 。

线程缺点

  1. 创建的时候需要切换到内核态,所以创建成本比较高。
  2. 切换的时候,需要用户态和内核态之间频繁的切换,切换成本较高。
  3. 线程数量有限制,当内核态线程过多时,会出现内核资源耗尽的情况。

用户级线程(协程)

       用户态线程简称协程,是完全由用户控制的线程,内核并不会感知到它的存在,用户级线程的创建、销毁、调度、状态变更以及其中的代码和数据都完全需要我们的程序自己去实现和处理。因为是存在在用户空间上的线程,所以在切换时不存在用户态和内核态的转换。

协程优点

  1. 不由内核管理,由用户自主管理,创建成本比较低。
  2. 不存在内核态和用户态的切换,切换成本比较低。
  3. 不需要操作系统去调度,所以可以跨操作系统,并且更加灵活、更容易控制。

协程缺点

  1. 因为操作系统的内核看不到协程,所以同属于一个进程的协程只能占有一个核,不能发挥多核优势。
  2. 操作系统不能主动调度协程,所以后面的协程只能等待前面的写成执行完才能获取到 CPU 资源。
  3. 同上,当前协程阻塞会导致后面的写成无法执行。
  4. 内核协作成本高,当要进行一些高权限的操作,比如读写文件时,需要频繁地进行用户态和内核态的切换。

调度器(GPM)

       GPMGo 语言运行时系统的重要组成部分
       其中 G 代表 goroutine 即协程,M 代表 machine 即系统线程、P 代表 Proccessor 代表写成和线程之间的联系

简单点理解就是:

G 是要被执行的任务实例
M 是实际的执行载体,需要绑定 P 成为一个执行单元才能调度 G
P 可以看作是任务处理器,P 中保存 M 执行 G 时的一些资源,P 决定了哪个 G 能配分配到哪个 M 上

G\P\M 之间的工作关系

       G 要调度到 M 上才能运行,M 需要关联 P 才可以执行 Go 代码,但当处理阻塞或系统调用中时,M 可以不用关联 P

       当进程启动时,会创建若干个(一般是内核数量)系统线程 M 和任务处理器 P,并一一绑定,因为一个线程对应一个 CPU 就不会出现上下文的切切换,能更大限度的节省资源。同时每一个任务处理器 P 都会对应一个私有的任务队列,但是私有队列有上限的,所以所有任务处理器还会有一个公用的全局队列。

       当有一个 G 被创建时,就会被放到一个任务处理器 P 的私有队列中等待被调度。如果所有的私有队列都满了,就会被放到全局队列中去。当 P 寻找 G 的时候,会先从自己的私有队列中寻找,如果没找到,再去全局队列中寻找,如果还是没有,它会去抢别的 P 中的 G。当任何地方都不能找到需要调度的 G 时,MP 则会断开连接。

       当 G 中进行了系统调用,则 M 也会进入系统调用状态,此时 P 会去寻找其他未在工作的 M 并为其寻找需要调度的任务。当 G 完成了系统调用,会进入空闲的私有队列或者全局队列,然后等待再次被调度。

       所以,GM 之间没有直接的联系,一个 G 可能被不同的 M 调度,一个 M 也可以调度不同的 G

Go 使用协程

创建协程

通过关键字 go 创建一个协程
一:普通函数创建

func goroutineTest(i int) {fmt.Println(i)
}
func main() {for i := 0; i < 10; i++ {go goroutineTest(i)}time.Sleep(time.Millisecond * 500)
}

二:匿名函数创建

func main() {for i := 0; i < 10; i++ {go func() {fmt.Println(i)}()}time.Sleep(time.Millisecond * 500)
}

三:匿名带参数函数创建

func main() {for i := 0; i < 10; i++ {go func(str string) {fmt.Println(str)}(fmt.Sprintf("%s%d", "s", i))}time.Sleep(time.Millisecond * 500)
}

注意

一:主协程不会等待子协程执行完毕
       以下列代码为例,一般来说控制台不会打印任何东西。原因是当代码运行到 go goroutineTest(i) 这一行时,并不是真正的会运行它,而是将它放到了任务队列中。所以可能子协程还没开始执行,主协程就已经退出了。所以我们可以再主协程加上等待。

func goroutineTest(i int) {fmt.Println(i)
}
func main() {for i := 0; i < 10; i++ {go goroutineTest(i)}time.Sleep(time.Millisecond * 500)
}

二:协程的执行没有顺序
       同上,当写成创建是,并不是立即执行,而是被分到不同的队列中等待被调度,而调度是不能保证先后顺序的(只能保证同一个队列中的任务先进先出),因此上述代码打印出来的结果大部分情况下时乱序的。
三:无参匿名函数中的变量变化

func main() {for i := 0; i < 3; i++ {go func() {fmt.Println(i)}()}time.Sleep(time.Millisecond * 500)
}

这段代码的打印结果如下:

2
2
3

       因为匿名函数不携带参数信息,只有匿名方法执行到 fmt.Println(i) 这一行时才会去读取 i 的值。又因为协程执行是有延迟的,所以当执行到这一句时, i 的值可能已经发生了变化。

下一篇再研究主协程等待子协程执行完毕以及确保子协程执行顺序的方法…

相关内容

热门资讯

FIBA期待杨瀚森表现 最新实... 北京时间6月25日消息,FIBA国际篮联公布了最新一期世界杯预选赛亚太区球队实力榜,中国男篮排在澳大...
收评:创业板指放量反弹涨2.8... 市场冲高回落后,再度震荡拉升。黄白线分化明显,权重股走势较强。量能明显放大,沪深两市成交额3.59万...
巨头财报引爆A股存储芯片板块,... 当地时间6月24日美股盘后, 美光科技(MU.US)公布截至5月31日的2026财年第三财季财报,业...
银行、消金公司助贷余额增速不得... 近日,中国证券报记者从多位业内人士处独家获悉,5月以来,多地金融监管部门对部分中小银行、消金公司下达...
朱鸿接任陈航,担任钉钉科技有限... 消费日报-今朝新闻讯 天眼查显示,6月23日,钉钉科技有限公司发生工商变更,陈航卸任法定代表人、董事...
3日累跌超20%,德创环保:公... 6月25日, 德创环保(603177.SH)公告,公司股票于2026年6月23日、6月24日和6月2...
北京发布2026年第七轮拟供商... 央广网北京6月25日消息(记者门庭婷)6月25日,北京市规划和自然资源委员会网站发布了2026年第七...
开放麦 | 启明创投胡奇:从A... “2026年,创投圈的浪潮再次翻涌:AI从技术概念走进产业深水区,硬科技创业从“小众赛道” 变成“主...
腾讯孙忠怀:在行业转身处 6月24日,2026腾讯视频年度发布在上海举行。腾讯公司副总裁、腾讯在线视频董事长孙忠怀以《在行业转...
加息,突变!美联储,重磅传来!... 美联储政策路径突生变数。 美国商务部经济分析局最新公布的数据显示,5月个人消费支出(PCE)物价指数...
6月合肥上门收金必看!5步避坑... 2026年6月,合肥黄金市场持续高位运行,不少市民翻出家里闲置的旧金饰、投资金条想变现,上门回收因为...
潮汕女富豪挂帅后加码液冷!祥鑫... 潮汕女强人,带着百亿公司加码液冷散热。 6月24日晚间,祥鑫科技(002965.SZ)公告称,公司董...
马斯克向太空要电,GobiX ... 一场关于「去哪里找电」的全球竞赛,正在朝两个方向展开。 作者|周永亮 编辑| 郑玄 「太空光伏是不是...
原料药行业陷入周期低谷 有药企... 每经记者|许立波 每经编辑|魏文艺 “过完年到现在,我们整个团队每个月都在出差,跑遍了亚非拉、欧美市...
家门口筛查白内障!永顺泽家镇暖... 大众卫生报·新湖南客户端6月25日讯(通讯员 彭雪姣)为切实解决辖区老年性白内障患者异地就医奔波、就...
终于等到!油价马上再大跌,这个... 点击添加图片描述(最多60个字) 编辑 各位车主朋友,好消息接二连三! 继6月18日油价大幅下调...
丈量出海新路 世界酒庄影响力指... 长期以来,全球酒庄评价体系由西方机构主导,且大多局限于单一酒种、单一评价维度,这一局面正逐渐被打破。...
峰瑞资本创始合伙人李丰:从资本... “2026年,创投圈的浪潮再次翻涌:AI从技术概念走进产业深水区,硬科技创业从“小众赛道” 变成“主...
原创 A... 迈向成熟,还有茁壮成长的机会。 作者 | 方璐 编辑丨于婞 来源 | 野马财经 2026年6月21日...
为企业解锁出海新通道!亚太中小... 6月24日下午,作为2026年APEC中小企业工商论坛的重要组成部分,亚太中小企业国际化合作发展论坛...