浅聊golang的并发设计

一 

5年没更新了,最近在研究golang的一些知识,大概总结了下golang的并发设计逻辑,随便聊聊,不涉及具体代码,只聊聊他的设计highlevel的逻辑。

我们大家都知道,在操作系统中存在用户态和内核态2种线程,在说golang的并发之前,我们可以看看其他语言提供的并发工具,比如java,提供了thread这个类的一些工具来让程序猿进行并发程序设计,但是性能其实并不高,下面是java并发的模型

如上图所示,我们假定只有单核CPU,那么让我们看看用java启动一个进程,里面做多线程的事情发生了什么

首先,在CPU的视角里面,3个OS线程都是要CPU去干活,好比你老板让你做3份活,你要去准备3份同样的工作所需的内容,在3份内容准备完毕之后呢,你就要开始干活了,这个时候你先去干第一份活,第一份活没干完又要去干第二份活,那你要记录下来第一份活干到什么程度了,下次再回来的时候接着干,第2份工作干到一半,又要去第三份那边干活,这个时候又要记录第2份工作干到什么程度了以便下次回来再接着干,第三份同样的逻辑。试试想象一下,理论上你一个人在干3个人的活,好像节省了时间,但是每次你要记录每一份活的状态,再切到另一个活那边,这个消耗是相当大的,以上同理到操作系统也是同样的道理。那么对应什么呢?

1 你--->就对应的CPU

2 3份工作 --->就对应你要创建的3个OS线程

3 你来回在3份工作切换--->就对应os线程的上下文切换

cpu的上下文切换开销是很大的,如果3个线程在同一个进程的执行环境里面,那么还会好一些,如果在不同的执行环境,那个时间消耗会更大,大概在不同的执行环境上下文切换会花1.8ms,相同执行环境会耗费0.4ms,主要是由于相同执行环境的线程共享进程的资源会比起切换到其他进程的消耗要小很多。

总结下就是:

1 创建OS线程是非常消耗时间和资源的,是很昂贵,所以创建的os线程必然会回因为数量的增多而提高性能

2 每一个os线程对cpu来讲都是一个task,每个task都要求要执行,这样的话就导致cpu会分时间片去公平的执行各个task,这个里面就涉及CPU频繁在各个OS线程间切换,消耗的时间很多,必然不会出现随着线程的并发数增多而提升性能。

二  用户态线程

开一开脑洞,那么我们能不能有一种办法,能把我们的task在用户态创建,然后绑定到提前创建好的OS线程里面呢,下图所示

我们在用户态实现一个调度器,把我们所有要并发执行的task交给调度器,让调度器来绑定到后台的os线程上面,如上图所示我们如果有n个并发的task交给调度器,让调度器帮助我们实现task和os线程的绑定,那么这样的话,在我们用户的视角,我实现了n个task的并发,在CPU的视角,我看到的只有3个OS线程,这样子的设计就可以满足我们的并发需求。为了更清楚的解释这个问题,还是如上图,如果没有调度器,我们自己实现多线程,那么创建n个os线程的代价实在太大,也无法保证性能提升。这里主要是解决前文说的cpu在多个os线程切换的性能问题,但是还是存在问题的,加入调度器把几个线程绑定在某一os线程执行,如果某一线程被阻塞,那么其他的线程也就阻塞,这个还是会有问题的。

三 golang是怎么做的?

针对2存在的问题,golang在语言层面也帮我们实现了并发的调度,也就是经典的GPM模型,这里我主要简单介绍下这个调度器怎么去解决上面的问题的,bi站有大佬讲的非常好,推荐刘丹冰大佬的GPM模型讲解,非常不错。

[典藏版]Golang调度器GPM原理与调度全分析 - 简书

golang的G:就是我们要并发执行的task

golang的P:主要是用来管理g的管理员

golang的M:主要是用来干活的把P里面的g绑定到后台的OS线程执行的

我们要做的就是定义好要并发的task,然后用go关键字并发就可以,很方便。

https://www.jianshu.com/p/fa696563c38a

具体GPM的并发模型讲解可以参考以上,我就不狗尾续貂了哈哈

我主要是想说golang的调度器在user线程阻塞如何保证绑定在同一个os线程的其他用户线程不阻塞,golang很好的解决了这个问题,主要思路是把阻塞的task摘下了,然后把P管理的其他task绑定到新创建的M上,等阻塞task好了之后再次调度到P上进行绑定到M上处理,非常牛逼,这个语言集成很多语言优点的大成,很值得学习并应用在未来工作中,在云原生时代,以K8s跟docker这类技术为代表的都是golang开发的,天然支持并发的特性,简洁的语法代码就能开发出高性能服务,累了,今天扯就到这里哈哈。。

 

补充一张进程线程图

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值