深入浅出理解进程、线程、协程

进程是什么

进程是计算机中的程序关于某数据集合上的一次运行活动,是系统进行资源分配和调度的基本单位,是操作系统结构的基础。

理解:当你运行一个程序,你就启动了一个进程。进程可以分为系统进程和用户进程。凡是用于完成操作系统的各种功能的进程就是系统进程,它们就是运行状态下的操作系统本身;用户进程就是由客户启动的进程,如开启qq、微信。

什么是多进程:

在同一时间里,同一个计算机系统中如果允许两个或两个以上的进程处于运行状态,这就是多任务,也就是多进程。

多进程的优点:

每个进程相互独立,不影响主程序的稳定性,一个进程崩了,也不会影响其他进程;
通过增加CPU,可以很容易扩充性能;
可以减少线程加锁、解锁的影响,极大提高性能(后面讲解线程是会讲解)
多进程的缺点:

逻辑控制复杂,需要和主程序交互; 需要跨进程边界,
需要跨进程边界,如果有大数据量传送,就不太好,适合小数据量传送、密集运算,所以进程开销比较大;
最好是多进程和多线程结合,即根据实际的需要,每个CPU开启一个子进程,这个子进程开启多线程可以为若干同类型的数据进行处理。
举例说明:

多进程带来的好处很明显,比如:我们可以同时在电脑上打开QQ、微信、还可以同时上网看小说,使用音乐播放器听音乐,这些任务之间不会相互干扰。
但是我们的计算机中如果只有一个CPU,那个原则上只能分配给一个进程,以便运行这个进程。要想同时运行多个进程,就必须使用并发技术。
并发的理解:思想可以理解为在操作系统的管理下,所有正在运行的进程轮流使用CPU,每个进程允许占用CPU的时间非常短,这样用户根本感觉不到CPU是在轮流为多个进程服务,就好像所有进程都在不断运行一样,实际上任务在一个时间有且仅有一个进程占有CPU。(如果不知道CPU是啥,可查写资料加深理解)

如果一台计算机上有多个CPU,情况就不一样了,我们分两种情况分析:当进程数小于CPU数的时候,每个进程都可以分配到不同的CPU来运行,这个时候,多进程就是在同一时间同时运行;当进程数大于CPU数的时候,还是需要使用并发技术。

———————————————————————华丽丽的分割线————————————————————————
线程是什么:

线程是轻量级的进程,是程序执行流的最小单元。线程是进程中的一个实体,是被系统独立调度和分派的基本单位,线程自己不拥有系统资源,但是所有同属进程下线程共享进程所拥有的全部资源。

理解:同一个进程中有多个线程,线程不能独立存在,必须依附于进程,一个进程至少有一个线程,如果只有一个线程,那就是程序本身。如:我们能在浏览器上同时打开多个网页。

什么是多线程:

进程内一个独立的、库调度的执行单元,是系统独立调度和分派CPU的基础单位。在单个程序中同时运行多个线程完成不同的工作,就是多线程。

多线程的优点:

无需跨进程边界;
程序逻辑和控制方式简单;
所有线程可以直接共享内存和变量等;
线程方式消耗的总资源比进程方式好;
多线程缺点:

每个线程与主程序共用地址空间,受限于2GB地址空间;
线程之间的同步和加锁控制比较麻烦;
一个线程的崩溃可能影响到整个程序的稳定性;
到达一定的线程数程序后,即使再增肌CPU也无法提升性能。
线程能提高的总性能优先,而且线程多了之后,线程本身的调度也是一个麻烦事儿,需要消耗较多的CPU。
举例说明:进行CPU分配是以线程为单位的,一个进程可能由多个线程组成。
总线程数<=CPU数量时:并行运行
总线程数>=CPU数量时:并发运行
并行运行的效率显然高于并发运行,所以在多CPU的计算机中,多任务的效率比较高。但是,在多CPU计算机中只有运行一个进程(线程),就不能发挥多CPU的优势。
———————————————————————华丽丽的分割线————————————————————————
什么是协程:

协程是一种用户级的轻量级线程。完全由用户控制。

协程拥有自己的寄存器上下文的栈。协程调度切换时,将寄存器上下文和栈保存到其他地方,在切回来的时候,恢复先前保存的寄存器上下文和栈。

因此协程能保留上次调用时的状态,每次过程重入时,就相当于上一次调用的状态。

协程需要用户自己编写调度逻辑,对于CPU来说,协程其实就是单线程,CPU不需要考虑怎么去调度、切换上下文,这样就省去了CPU的切换开销,因此协程在一定程度上要好于多线程。

并发:并发是指一个时间段内,有几个程序在同一个CPU上运行,但是任意时刻只有一个程序在CPU上运行。

并行: 指任意时刻点上,有多个程序同时运行在多个CPU上

同步:指代码调用IO操作时,必须等待IO操作完成才返回的调用方式。

异步:指代码调用IO操作时,不必要等IO操作完成就返回的调用方式。

阻塞:指调用函数时候当前线程被挂起

非堵塞:指调用函数时候当前线程不会被挂起,而是立即返回。

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

举例说明:生产者消费者模式

两个线程,一个线程向队列中放数据,另一个从队列中取数据,处理起两个线程的协作就显得很麻烦,不但需要加锁,还得做好线程的通知和等待。

生产者生产数据,消费者接受数据,生产者发送数据,暂停运行,不进行下一轮循环,消费者等到数据,知道数据到来,取出进行处理,消费者在循环中再次yield,暂停执行,生产者继续下一次的循环,生成新的消息,发送给消费者
协程和线程似乎很像,每次协程停止执行的时候,也得保存现场,要不然没法恢复执行。

这种模式比线程更加轻量级,操作系统内核不用参与,相当于用户态线程了,协程的开销极小,可以轻松地创建大量的协程来做事情。 对了,也许你注意到了,我这两个协程是’合作式’的,它们两个同一时刻只能有一个在运行。 实际上,我在底层可以用一个线程去执行这两个协程。

既然两个程序可以’合作’,那就不用加锁了,也不用在代码里写什么wait和notify了,在程序层面,可以用同步的方式实现异步的功能。

协程的优点:

无须线程上下文切换的开销;
无须原子操作锁定及同步的开销,原子操作就死一个最小的操作;
方便切换控制流,简化编程模型;
高并发性、高扩展性、低成本;
协程的缺点:

无法利用多核资源:协程的本质就是单线程,它不能同时将单个CPU的多核用上,协程需要配合进程才能运行在多核CPU上,
进程堵塞操作会堵塞掉整个程序

发表评论