
课程咨询: 400-996-5531 / 投诉建议: 400-111-8989
认真做教育 专心促就业
计算机编程开发行业在大多数行业中是比较赚钱的一个行业,今天我们就通过案例分析来了解一下,软件开发进程线程与协程之间的关系。
进程
在早期的单任务计算机中,用户一次只能提交一个作业,独享系统的全部资源,同时也只能干一件事情。进行计算时不能进行IO读写,但CPU与IO的速度存在巨大差异,一个作业在CPU上所花费的时间非常少,大部分时间在等待IO。
为了更合理的利用CPU资源,把内存划分为多块,不同程序使用各自的内存空间互不干扰,这里单独的程序就是一个进程,CPU可以在多个进程之间切换执行,让CPU的利用率变高。
为了实现CPU在多个进程之间切换,需要保存进程的上下文(如程序计数器、栈、内核数据结构等等),以便下次切换回来可以恢复执行。还需要一种调度算法,Linux中采用了基于时间片和优先级的完全公平调度算法。
线程
多进程的出现是为了解决CPU利用率的问题,那为什么还需要线程?答案是为了减少上下文切换时的开销。
进程在如下两个时间点可能会让出CPU,进行CPU切换:
进程阻塞,如网络阻塞、代码层面的阻塞(锁、sleep等)、系统调用等
进程时间片用完,让出CPU
而进程切换CPU时需要进行这两步:
切换页目录以使用新的地址空间
切换内核栈和硬件上下文
进程和线程在Linux中没有本质区别,他们大的不同就是进程有自己独立的内存空间,而线程(同进程中)是共享内存空间。
在进程切换时需要转换内存地址空间,而线程切换没有这个动作,所以线程切换比进程切换代价更小。
为什么内存地址空间转换这么慢?Linux实现中,每个进程的地址空间都是虚拟的,虚拟地址空间转换到物理地址空间需要查页表,这个查询是很慢的过程,因此会用一种叫做TLB的cache来加速,当进程切换后,TLB也随之失效了,所以会变慢。
综上,线程是为了降低进程切换过程中的开销。
协程
当我们的程序是IO密集型时(如web服务器、网关等),为了追求高吞吐,有两种思路:
为每个请求开一个线程处理,为了降低线程的创建开销,可以使用线程池技术,理论上线程池越大,则吞吐越高,但线程池越大,CPU花在切换上的开销也越大
线程的创建、销毁都需要调用系统调用,每次请求都创建,高并发下开销就显得很大,而且线程占用内存是MB级别,数量不能太多
为什么线程越多cpu切换越多?准确来说是可执行的线程越多,cpu切换越多,因为操作系统的调度要保证绝对公平,有可执行线程时,一定是要雨露均沾,所以切换次数变多
使用异步非阻塞的开发模型,用一个进程或线程接收请求,然后通过IO多路复用让进程或线程不阻塞,省去上下文切换的开销
这两个方案,优缺点都很明显,方案1实现简单,但性能不高;方案2性能非常好,但实现起来复杂。有没有介于这两者之间的方案?既要简单,又要性能高,协程就解决了这个问题。
协程是用户视角的一种抽象,操作系统并没有这个概念,其主要思想是在用户态实现调度算法,用少量线程完成大量任务的调度。
【免责声明】:本内容转载于网络,转载目的在于传递信息。文章内容为作者个人意见,本平台对文中陈述、观点保持中立,不对所包含内容的准确性、可靠性与完整性提供形式地保证。请读者仅作参考。更多内容请加danei0707学习了解。欢迎关注“达内在线”参与分销,赚更多好礼。