一步一步写线程之十五协程

236 篇文章 96 订阅
44 篇文章 6 订阅

一、进程、线程和协程

在前面分析过几次c++库提供的协程应用,包括例程和代码也都分别给了说明。这次在线程的开发中,就从另外一个角度来分析协程。大家都知道,科学技术的进步是从一点一滴逐渐发展起来的。计算机技术也脱离不开这个规律。
最初的程序是直接输入计算机进行运行的且不可以同时进行多个程序,但计算机的资源在当时是十分昂贵的,这就迫使应用者需要有一种手段来满足多个程序同时运行。在这种实际需求不断的推进下,逐渐演变出来OS(操作系统),操作系统又从进程,发展出线程再到现在提到的协程(在Windows上曾叫过纤程)。

二、三者间的关系和发展

正如操作系统发展的历程,从单一独占到批处理、多道程。随着硬件技术的快速发展,特别是CPU和内存技术的快速迭代,促进操作系统迅速发展到现在常见的通用操作系统(此处不讨论实时等其它较为专业的OS)。
当个人计算机(特别是手机)随着社会发展完全普及以后,多元化的需求,使得操作系统变更更复杂和精密。而复杂和精密就代表着一般人是无法轻易的基于OS进行编程,所以就需要OS对其中一些技术进行更新。
好,简单的回顾是为了引出进程、线程和协程。开发者开发的程序,体现在计算机中,就是一个进程,进程是资源分配的基本单位。也就是说,在只有进程的情况下,开发者只能面向进程对各种资源进行处理。如果单纯是一个进程,这事情未必是个坏事。自己的事情自己从头到脚全程管理跟踪,反而可能更好的处理各种问题。但实际情况是,往往会有很多进程需要创建出来,更恐怖的是,这些进程间需要互相通信和交换数据。进程间通信就好比两个家庭要互换资源,可能涉及到安全、速度、效率和顺序等等问题。而且可能如果进程因为某种情况需要互斥,那么大量的资源等于是在被闲置,这是浪费啊,浪费是最大的犯罪。
所以就有高人推出了线程,线程是什么?是共享进程资源的一大堆可执行单元。就好比自己家里的几个孩子间互相交换玩具,一是限定了交换的范围,二是不需要过多的安全考虑,效率这不就大幅提升起来了嘛。即使出现个别线程阻塞,也只是浪费一部分资源,这是不是另一个角度上的分治法?
但问题到此不会停止,社会最初对计算机的要求就是类似计算弹道啥的,数据扔进去,尽快出来就行,等会儿就等会儿。可到了现在,可能我要下载一个大数据文件,又要看一个文档并修改完善,而且此时耳机中还要从电脑中播放音乐,甚至有的人可能还会不时盯一眼正在玩儿着程序。这些任务中,有需要同步的,比如修改文件必须立刻体现出来,也有异步的,比如下载文件,有的还可能是同步异步一起的,比如游戏。这里面就带来一个问题。一个线程搞不定,需要N个线程来实现,这些线程间互相争抢资源和运行时间,复杂度就一下子上来了。
多线程编程一直是编程界的扛把子,就是这个原因。异步(异步主流基本都是多线程,当然也有其它),就意味着不确定性。同步和异步混合编程,特别是在一个业务流水中,可能意味着要硬生生的把两个不对付的人硬捏合在一起。所以对开发者的要求一下子提高了上来,既需要对OS中对线程的调度有清晰的了解,又要明白业务逻辑的流程,还要把把二者结合起来,最后还要将各个线程的利用最大化,凡此种种。可以不负责的说,现在编程,几乎是绕不开多线程的。
而真正既懂底层,又熟练于语言本身,还掌握多线程技术,还对业务流程通晓的,就已经是少数人了。更何况,还要加上对线程的利用率的要求,也就是要最大发挥出异步和同步的威力。可以想见的艰难。或许有人说,我没见过有多难啊,身边很多人都在写多线程啊?So Easy。确实如此,在现在很多的编程的场景中,其实对上面的要求不高,再加上库或框架的加持,其实没有多少难度,这反而印证了上面的话,绝大多数人对多线程编程掌握的不深。所谓不难,是因为需求相对简单。
大路不平旁人铲。协程或者纤程就出现了。可不可以设计一个更轻量级的线程,它完全可以由用户来控制。线程之所以难,一个重要原因是管理和调度是由内核来进行的,用户层只能因势利导,不能我行我素。而这个轻量级的线程就是协程(正如早期把线程叫轻量级进程)。异步的目的是为了让资源更合理的使用和更加适配整体的业务流程,可其也因此引入了复杂性。那么可不可以使用同步来实现异步实现的功能呢?
先扯远一些,看看硬件,大家都知道,IO并行一次可以传输更多的数据,相同的条件下,理论上并行要比串行多出并行数量的位数。但实际情况下,并行传输IO口已经被串行替代了。原因在于并行的传输距离短,数据难于保证同步。而随着串行时钟提高压缩算法等等的引入,反而得到了长足的进步。
协程也有些类似,同步浪费资源,但只要把资源的浪费限定在可忍受的范围内,多增加一些协程的数量不影响对外的操作不就可以了吗?这其实是一种解决问题的思路,只要把协程做的足够多让其串行执行不就可以达到异步的目的么。
为什么反复提编程思想才是最重要的,就是这个原因。

三、未来发展的方向

虚拟化,是近些年来不断提到的概念。协程会不会仍然有些复杂,大量的协程会不会又引出另外的问题?这些天在分析XDP,其基于的eBPF,也是以字节码在虚拟沙箱中运行。而在一些语言如Java中,提出了 Virtual Thread的概念,通过进一步隔离内核与应用的复杂对应关系,更进一步的减少了开发的难度。特别是并行编程的出现,这种虚拟的线程可能更适应此类开发环境。
技术发展的未来,永远是朝着简单易用安全可靠方向前进的。一个线程的创建、管理、销毁和回收,都需要一个很长的时间(对CPU来说),而且多核和多CPU的电脑又会要求各种的手段来适配物理执行单元和线程执行单元。这也导致了整体上并行能力的提高与开发者的水平有着强相关。回过头来看,多线程编程逐步成为主流,不也是因为多进程编程更重更难于驾驭么?
所以未来发展的方向一定是让创建线程尤如定义变量一样简单方便,让所谓异步编程只需要指定处理结果的索引即可,更甚至可能没有了同步异步之说。什么复杂的同步机制、内存序、栅栏、信号等等,都被屏蔽在底层框架甚至于OS内。
这个愿望非常美好,但肯定有高手在朝着这个方向努力前进。日拱一卒吧。

四、总结

人难得是选择,选择是最痛苦的。但一旦选择完成,朝着方向前进,其实反而没有什么可痛苦的了。今天讲协程,没有继续于以往的技术实现的原理和实现的框架或者应用的方法,而是从另外一个角度分析其在计算机发展过程上的定位。言简意浅,与诸君共勉!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值