Python 进程,线程, 协程
1. 进程
进程是系统进行资源分配和调度的一个独立单位(最小单位)。
进程的几个状态
空->新建:创建执行一个程序的新进程,可能的事件有:新的批处理作业、交互登录(终端用户登录到系统)、操作系统因为提供一项服务而创建、由现有的进程派生等。
新建->就绪:操作系统准备好再接纳一个进程时,把一个进程从新建态转换为就绪态。
就绪->运行:需要选择一个新进程运行时,操作系统的调度器或分配器根据某种调度算法选择一个处于就绪态的进程。
运行->退出:导致进程终止的原因有:正常完成、超过时限、系统无法满足进程需要的内存空间、进程试图访问不允许访问的内存单元(越界)、算术错误(如除以0或存储大于硬件可以接纳的数字)、父进程终止(操作系统可能会自动终止该进程所有的后代进程)、父进程请求终止后代进程等。
运行->就绪:最常见的原因是,正在运行的进程到达了“允许不中断执行”的最大时间段,该把处理器的资源释放给其他在就绪态的进程使用了;还有一中原因可能是由于具有更改优先级的就绪态进程抢占了该进程的资源,使其被中断转换到就绪态。
运行->阻塞:如果进程请求它必须等待的某些事件,例如一个无法立即得到的资源(如I/O操作),只有在获得等待的资源后才能继续进程的执行,则进入等待态(阻塞态)。
阻塞->就绪:当等待的事件发生时,处于阻塞态的进程转换到就绪态。
就绪->退出:在上图中没有标出这种转换,在某些进程中,父进程可以在任何时刻终止一个子进程,如果一个父进程终止,所有相关的子进程都被终止。
阻塞->退出:跟上一项原因类似。
2. 线程
线程是需要维护线程栈的
线程的调度是在内核态运行的(内核要安排CPU给线程使用----由进程来调度)
操作系统是看不见线程的(操作系统控制进程,而进程调度线程)
什么是用户态,什么又是内核态?
用户态:当一个进程在执行用户自己的代码时处于用户状态
内核态:当一个进程因为系统的调用陷入内核代码中执行处于内核运行态
线程和进程共享栈数据之外的所有数据
线程与资源分配无关,它属于某一个进程,并与进程内的其他线程一起共享进程的资源
为什么说切换线程需要资源的开销?
线程中的代码是在用户态运行
线程的切换会导致用户态和内核态切换,所以需要资源的开销。
只是切换的时候在内核态,有没有方法实现,切换的过程也在用户态呀?
有----协程
协程的代码时程序员自己写的,协程的切换不需要进程干涉,完全由程序员自己做主,
换句话说,协程的调度与进程无关,即与操作系统无关,与内核无关。
线程与协程的特点?
线程的切换需要擦欧总系统的干涉(因为线程的切换需要进程调度)
协程的切换不需要操作系统的干涉(因为协程的切换不需要进程调度,完全由程序员写的代码调度)
说说进程和线程之间的区别?
-
进程是系统进行资源分配和调度的一个独立的单位
-
线程是进程的一个实体,是程序执行的最小单元
-
进程是资源分配的最小单位,线程是程序执行的最小单位(进程包含线程)
-
进程有自己独立的地址空间,每启动一个进程,系统就会分配地址空间,开销大线程是共享进程之间的数据的,使用相同的地址空间,因此CPU切换线程比进程花费小,同时创建线程比创建进程开销小很多
-
多进程程序更健壮,多线程程序只要有一个线程死掉了,整个进程也就死掉了,而一个进程死了不会影响其他进程,因为进程有独立的地址空间
3. 协程
-
协成是单线程的并发,协成是一种用户态的轻量级线程(微线程),即协成是由用户程序自己控制调度的
-
线程遇到 I/O操作会等待、阻塞,协成遇到I/O会自动切换(剩下的只有CPU操作)
-
线程的状态保存在CPU的寄存器和栈里而协程拥有自己的空间,所以无需上下文切换的开销,所以快
-
协成的切换开销小,属于程序级别的切换,操作系统完全感知不到,因而钢架轻量级
-
单线程内就可以实现并发的效果,最大限度的利用CPU
协程是一种实现在线程内部用户态切换的技术
协程的优势:上下文执行状态都在生成器中维护,不需要维护协程栈
asyncio使用的是事件循环——EventLoop,记录所有协程任务并计划何时执行
协程的思想:主动让出控制权,恢复控制权