进程、线程、协程(转)

进程是执行着的应用程序,而线程是进程内部的一个执行序列。一个进程可以有多个线程。线程又叫做轻量级进程。

 

进程是让操作系统的伪并发性成为可能

线程是让进程里面内部子任务的并发成为可能

最终目标是提高cpu的利用率

 

进程是系统分配的最小单元,线程是cpu调度的最小单元

进程是具有一定功能的程序关于某个数据集合上的一次运行活动,进程是系统进行资源调度和分配的一个独立单位。

线程是进程的实体,是CPU调度和分派的基本单位,它是比进程更小的能独立运行的基本单位。

一个进程可以有多个线程,多个线程也可以并发执行

 

进程的生命周期:创建-就绪-运行-等待-死亡

线程的生命周期:新建-就绪-运行-阻塞-等待-锁池-死亡

 

两者的对比:

1、调度方面:在引入线程的OS中,线程是独立的调度和分派单位,而进程作为资源的拥有单位(相当于把未引入线程的传统OS中的进程的两个属性分开了)。由于线程不拥有资源,因此可以显著的提高并发度以及减少切换开销。

2、并发性:引入了线程的OS中,进程间可以并发,而且一个进程内部的多个线程之间也是可以并发的,这就使OS具有更好的并发性,有效的提高了系统资源利用率和吞吐量。

3、拥有资源:无论OS是否支持线程,进程都是基本的资源拥有单位,线程只拥有很少的基本的资源,但是线程可以访问所隶属的进程的资源(进程的代码段,数据段和所拥有的系统资源如fd)

4、系统开销:创建或者撤销进程的时候,系统要为之创建或回收PCB,系统资源等,切换时也需要保存和恢复CPU环境。而线程的切换只需要保存和恢复少量的寄存器,不涉及存储器管理方面的工作,所以开销较小。此外,统一进程中的多个线程由于共享地址空间,所以通信同步等都比较方便。

 

如何理解一个程序可以对应多个进程,一个进程也可以对应多个程序?

        一个程序可以重复运行,开几个窗口,比如网游的“双开”,一个进程可以对应多个程序就是一个DLL文件可以被多个程序运用,比如DirectX9的动态链接库,就是,许多游戏都要有它才能运行。这就如同的车和路的关系,要去一个地方,可以有多条路,而一条路也可到达多个地方。

 

 

从其他方面诠释:

        一开始大家想要同一时间执行那么三五个程序,大家能一块跑一跑。特别是UI什么的,别一上计算量比较大的玩意就跟死机一样。于是就有了并发,从程序员的角度可以看成是多个独立的逻辑流。内部可以是多cpu并行,也可以是单cpu时间分片,能快速的切换逻辑流,看起来像是大家一块跑的就行。

        但是一块跑就有问题了。我计算到一半,刚把多次方程解到最后一步,你突然插进来,我的中间状态咋办,我用来储存的内存被你覆盖了咋办?所以跑在一个cpu里面的并发都需要处理上下文切换的问题。进程就是这样抽象出来的一个概念,搭配虚拟内存、进程表之类的东西,用来管理独立的程序运行、切换。

        后来一个电脑上有了好几个cpu,好咧,大家都别闲着,一人跑一个进程。就是所谓的并行。

        因为程序的使用涉及大量的计算机资源配置,把这活随意的交给用户程序,非常容易让整个系统分分钟被搞跪,资源分配也很难做到相对的公平。所以核心的操作需要陷入内核(kernel),切换到操作系统,让老大帮你来做。

        有的时候碰着I/O访问,阻塞了后面所有的计算。空着也是空着,老大就直接把CPU切换到其他进程,让人家先用着。当然除了I\O阻塞,还有时钟阻塞等。一开始大家都这样弄,后来发现不成,太慢了。为啥呀,一切换进程得反复进入内核,置换掉一大堆状态。进程数一高,大部分系统资源就被进程切换给吃掉了。后来搞出线程的概念,大致意思就是,这个地方阻塞了,但我还有其他地方的逻辑流可以计算,这些逻辑流是共享一个地址空间的,不用特别麻烦的切换页表、刷新TLB,只要把寄存器刷新一遍就行,能比切换进程开销少点。

        如果连时钟阻塞、 线程切换这些功能我们都不需要了,自己在进程里面写一个逻辑流调度的东西。那么我们即可以利用到并发优势,又可以避免反复系统调用,还有进程切换造成的开销,分分钟给你上几千个逻辑流不费力。这就是用户态线程。

        从上面可以看到,实现一个用户态线程有两个必须要处理的问题:一是碰着阻塞式I\O会导致整个进程被挂起;二是由于缺乏时钟阻塞,进程需要自己拥有调度线程的能力。如果一种实现使得每个线程需要自己通过调用某个方法,主动交出控制权。那么我们就称这种用户态线程是协作式的,即是协程。

        本质上协程就是用户空间下的线程。

 

用户线程与内核线程

       根据操作系统内核是否对线程可感知,可以把线程分为内核线程和用户线程。

引入用户线程,具体而言,有以下四个方面的优势:

    (1)可以在不支持线程的操作系统中实现。
    (2)创建和销毁线程、线程切换代价和线程管理的代价比内核线程少得多。
    (3)允许每个进程定制自己的调度算法,线程管理比较灵活。
    (4)用户线程能够利用的表空间和堆栈空间比内核级线程多。

用户线程的缺点主要有以下两点:
    (1)同一进程中只能同时有一个线程在运行,如果有一个线程使用了系统调用而阻塞,那么整个进程都会被挂起。
    (2)页面失效也会产生类似的问题。

 

参考链接:

https://mp.weixin.qq.com/s/zuWRx1FGuBC-_HwuA7jK3w

原文:https://blog.csdn.net/qq_35642036/article/details/82798749 

posted on 2019-05-24 12:09  NetPig  阅读(181)  评论(0编辑  收藏  举报

导航