可以拥有自己的独立资源 | 切换消耗 | 是资源分配单位 | 是执行单元 | |
---|---|---|---|---|
进程 | 可以 | 消耗大 | 是 | 否 |
线程 | 不可以 | 消耗小 | 否 | 是 |
进程是资源容器,我们只会说一个进程占用了多少内存,而从来不会说一个线程占用了多少内存。资源归属于进程,线程却拥有资源的使用权。
线程的概念是建立在进程的基础上的,一个进程至少有一个主线程,有0个或多个子线程,这些线程共用这个进程所申请的资源,因此才会有线程间同步与资源互斥这些概念。由于进程已经是资源分配的单位,因此,进程与进程之间都是相互隔离的,就如同一家一户,各有各的围墙,各有各的宅基地,线程如同家庭里的亲人,这些亲人共同使用家里的资源。
本质上,是线程在执行,进程只是负责申请资源,因此线程才是操作系统调度的最小单位。对于操作系统来说,在进程之间进行切换,就如同从一个住宅切换到另一家住宅,而在线程间切换,就如同从房子的一间卧室切换到客厅。线程间切换要比进程间切换容易的多。
进程,线程是大家非常熟悉的概念,然而说到协程,很多人表示懵逼了,关于协程,要准确掌握以下两个概念
协程是线程的异步编程模型,因此我才说,协程在一个线程中存在,我特意强调一个线程,是想让你明确一点,系统并没有创建出若干个协程来进行工作,在这个线程中,存在多个子程序,假设有子程序A,B,C,那么最初是A在执行,中途遇到了IO,于是停止A,执行B,然后B中也遇到了IO,这个时候再回来执行A,A执行结束后再执行C
你会看到,在一个线程内,A,B,C三个子程序互相协调工作,这个就是协程。这里所谓的子程序,你可以理解为函数,但是执行过程又不是函数之间的调用,因为代码里,这三个函数并不存在调用关系,他们可能都是在爬取一个url里的内容,各自的运行是独立的,但是子程序在执行过程中发生了中断,将控制权交出,在适当的时候返回来继续执行。
线程是系统创建的,具体什么时候执行,执行多久,都是由系统决定的,而协程则是程序自己创建的,在python中,yield 和gevent都可以实现协程。
python的多线程由于存在GIL锁,因此一个时刻只有一个线程在运行,如果你起了10个线程,那么CPU要在这10个线程之间不停的切换,每个线程都有自己的一组CUP寄存器,这里保存了线程的上下文,线程之间的切换是会耗费资源的,线程越多,切换的越频繁,耗费的资源也就越多。
协程之间也存在切换,但是这些协程都是在一个线程中,由程序自身负责切换,而不是CPU负责切换,这种切换相比于线程之间的切换就快的多了,协程拥有自己的寄存器上下文和栈,当需要切换时,将这些内容保存到其他地方,需要切换回来时,将这些内容回复回来,找到上一次离开时所处的逻辑流位置并继续执行。
线程之间对共享资源的访问必须加锁,但协程不需要,原因很简单,协程始终生存在于一个线程中,根本不存在同时修改一个共享资源的情况。
协程是在线程层面上进行了拆分,与线程相关的是抢占式多任务,与协程相关的是协作式多任务。
如果没有协程,当一个线程内遇到IO等待时,会切换到别的线程去执行,但是有了协程,一个线程内的某个子程序遇到IO等待时,会将控制权交给同在线程内的其他子程序,没有了线程之间的切换,没有了锁,效率自然变高了。
QQ交流群: 211426309