进程:

  一个运行的程序(代码)就是一个进程,没有运行的代码叫程序,进程是系统资源分配的最小单位,进程拥有自己独立的内存空间,所以进程间数据不共享、开销大。

线程:

  调度执行的最小单位,也叫执行路径,不能独立存在,依赖进程存在一个进程至少有一个线程,叫主线程,而多个线程共享内存(数据共享,共享全局变量),从而极大的提高了程序的运行效率。

协程:

  是一种用户态的轻量级线程,协程的调度完全由用户控制,协程拥有自己的寄存器上下文和栈,协程调度切换时。将寄存器上下文和栈保存到其他地方,在切回来的时候,恢复先前保存的寄存器和上下文和栈,直接操作栈基本没有内核切换的开销,可以不加锁的访问全局变量,所以上下文的切换非常快。

什么时线程竞争?

  线程时非独立的,同一个进程里线程是数据共享的,当各个线程方位数据资源时会出现竞争状态即:  

    数据几乎同步会被多个线程占用,造成数据混乱,即所谓的线程不安全,那怎么解决多线程竞争问题? -- 锁

 锁的好处:

    确保了某段关键代码(共享数据资源)只能由一个线程从头到尾完整的执行能解决多线竞争下的原子操作问题。

 锁的坏处:  

     阻止了多线程并发执行,包含锁的某段代码实际上只能以单线程模式执行,效率大大的降低了,锁的致命问题:死锁。

多进程:

  在Linux系统下,使用 os.fork(), 调用一次,返回两次,操作系统自动把当前进程(父进程)复制一份(子进程),然后分别在父进程和子进程内返回。子进行永远返回 0 , 父进程返回子进程的 ID,经过这样做,父进程就能 fork() 出很多子进程了,并可以记录下子进程的 ID号了。子进程可以通过 getppid() 来获取父经常ID,fork() 仅在 Unix / Linux 下使用,windows 则不行,所以,在 Python 中,存在一个跨平台的包 (mutiprocessing),通过引入包中的 Process 类,就可以创建多进程程序了。

  可以创建一个进程 p = Process(target = func, args = (*.)),然后利用 p.start() 及 p.join()方法可以等待子进程结束后才往下执行,通常用于进程间同步。另外,可以用进程池的方式,例如 p = Pool(n). 然后 p.apply_asunc(func,args),这里可以使用 n 种不同的参数传入,建立不同的进程,用这种方式时,在调用 join() 方法前,要先调用 close() 方法,使得不能再添加新的线程, mutipeocessing 包里提供了 Qeue、Pipe 等多种进程间同行的方法。可以直接引入 Queue类,实例化一个对象,则不同的进程可以使用 put 方法发信息,同时可以使用 get 方法去信息。

多线程:

  多个任务可以创建多个进程来完成,同时也可以创建多个线程来完成,线程时操作系统直接执行的单元, Python 含有 threading 这个高级模块,要启动一个线程,就是把一个函数传出并创建 Thread 实例,然后调用 start() 方法开始执行,例如 t = threading.Thread(target = func, name = *), 注意这里的 name 属性,它是给线程命名的,缺省值为 Thread - 1 .... 。要注意的是,刚才说了,任何一个进程都含有一个线程,而这个主线程则执行着我们编写的程序,可以调用 threading.current_thread().name() 来查看他,它的名字就叫做 MainThread.

  再多线程编程中,有一个最大的问题就在于进程内的资源被各个线程共享,进程内任何变量都可以被任何一个线程修改,因此,线程之间若去修改同一个变量。则可能导致程序出 Bug,所以,引入了锁机制,当某个线程去修改某个变量时,可以再变量所在的方法内加一把锁,使得其他线程不能同时执行该方法,只有释放了锁后,其他线程才能获得修改权。

  创建一个锁是 通过 lock = threading.Lock() 来说实现的,可以使用 try...finally...语句,在 try...之前使用 lock.acquire() 获得锁,然后再 try 语句里面修改变量,然后在 finally 里加 lock.close() 来保证锁一定被释放,避免称为一个死锁。

区别与联系:

  多进程的优点是稳定性好,一个子进程崩溃了。不会影响主进程以及其他进程,但是缺点是创建进程的代价非常大,因为操作系统要给每个进程分配固定的资源,并且,操作系统对进程的总数会有一定的限制,若进程太多,操作系统调度都会存在问题,会造成假死状态。

  多线程优点是效率高一点,但是致命的缺点是任何一个线程崩溃都有可能造成整个进程崩溃,因为他们共享了进程的内存资源池。对于任务数来说,无论是多进程或者多线程,都不能太多,因为操作系统在切换任务时,会由一系列的保护现场的措施,这要花费相当多的系统资源,如任务过多。则大部分资源都被用做干这些了。结果就是所有任务都做不好。所以操作系统会限制进程的数量,另外,考虑计算密集型及IO 密集型应用程序,对于计算密集型,多任务势必造成资源浪费,对于 IO 密集型,因为 IO 速度远低于 CPU 计算速度,所以使用多任务方式可以大大增加程序运行效率。

   协程,又称作为线程, 英文名 Coroutine。

    协程是 Python 中另外一种实现多任务的方式,值不过比线程更小占用的执行单元(理解为需要的资源)。为啥说它是一个执行单元,因为他系带CPU 上下文。这样只要在适合的时机,我们可以把一个协程切换到拎一个协程。只要这个过程中保存或恢复 CPU 上下文那么程序还是可以运行的,

    在实现多任务时,线程切换从系统层面远不止保存和恢复 CPU 上下文这么简单,操作系统为了程序运行的高效性每个线程都有自己缓存 Cache 等等数据,操作系统还会帮你做这些数据的恢复操作。所以线程的切换非常耗性能,但是协程的切换只是单纯的操作 CPU 的上下文,所以一秒钟切换个上百万次系统都扛得住。

  协程 -> 为线程 在不开辟线程的情况下 完成多个任务 “交替执行” 网络爬虫

  协程是一种特殊的生成器

  yeild 返回值 生成器

  yeild 协程 (没返回值就是协程)

  greenlet 已经实现了协程,但是这个还得人工切换,是不是觉得太麻烦,不要着急, python 还有一个比 greenlet 更强大的并且能够自动i切换任务的模块 gevent

  其原理是当一个 greenlet 遇到 IO(指的是 input、 output 输入输出、比如网络、文件操作)操作时,比如访问网络、就自动切换到其他的 greenlet、等到 IO 操作完成,再再适当的时候切换回来继续执行,由于 IO 操作非常耗时,经常使程序处于等待状态,有了 gevent 为我们自动切换协程,就保证总有 greenlet 再运行,而不是等待 IO。

  简单总结:

    1、进程是资源分配的单位

    2、线程是操作系统调度的单位

    3、进程切换需要的资源很大,效率很低

    4、线程切换需要资源一般,效率一般(不考虑 GIL 的情况下)

    5、协程i切换任务资源很小、效率高

    6、多进程、多线程、根据 CPU 核数不一样可能是并行的,但是协程是在一个线程中,所以是并发

   

Python 中多进程、多线程、协程的更多相关文章

  1. python采用 多进程/多线程/协程 写爬虫以及性能对比,牛逼的分分钟就将一个网站爬下来!

    首先我们来了解下python中的进程,线程以及协程! 从计算机硬件角度: 计算机的核心是CPU,承担了所有的计算任务.一个CPU,在一个时间切片里只能运行一个程序. 从操作系统的角度: 进程和线程,都 ...

  2. python 多进程/多线程/协程 同步异步

    这篇主要是对概念的理解: 1.异步和多线程区别:二者不是一个同等关系,异步是最终目的,多线程只是我们实现异步的一种手段.异步是当一个调用请求发送给被调用者,而调用者不用等待其结果的返回而可以做其它的事 ...

  3. Python 多进程 多线程 协程 I/O多路复用

    引言 在学习Python多进程.多线程之前,先脑补一下如下场景: 说有这么一道题:小红烧水需要10分钟,拖地需要5分钟,洗菜需要5分钟,如果一样一样去干,就是简单的加法,全部做完,需要20分钟:但是, ...

  4. python中线程 进程 协程

    多线程:#线程的并发是利用cpu上下文的切换(是并发,不是并行)#多线程执行的顺序是无序的#多线程共享全局变量#线程是继承在进程里的,没有进程就没有线程#GIL全局解释器锁#只要在进行耗时的IO操作的 ...

  5. Python中进程线程协程小结

    进程与线程的概念 进程 程序仅仅只是一堆代码而已,而进程指的是程序的运行过程.需要强调的是:同一个程序执行两次,那也是两个进程. 进程:资源管理单位(容器). 线程:最小执行单位,管理线程的是进程. ...

  6. python中普通函数调用协程

    import asyncio def target(loop, timeout=None): future = asyncio.run_coroutine_threadsafe(add(1, b=2) ...

  7. python中多进程+协程的使用以及为什么要用它

    前面讲了为什么python里推荐用多进程而不是多线程,但是多进程也有其自己的限制:相比线程更加笨重.切换耗时更长,并且在python的多进程下,进程数量不推荐超过CPU核心数(一个进程只有一个GIL, ...

  8. python 多线程, 多进程, 协程

    1. 介绍: threading用于提供线程相关的操作,线程是应用程序中工作的最小单元.python当前版本的多线程库没有实现优先级.线程组,线程也不能被停止.暂停.恢复.中断. 2. 1  线程执行 ...

  9. Python多线程、多进程和协程的实例讲解

    线程.进程和协程是什么 线程.进程和协程的详细概念解释和原理剖析不是本文的重点,本文重点讲述在Python中怎样实际使用这三种东西 参考: 进程.线程.协程之概念理解 进程(Process)是计算机中 ...

  10. python爬虫——多线程+协程(threading+gevent)

    上一篇博客中我介绍了如何将爬虫改造为多进程爬虫,但是这种方法对爬虫效率的提升不是非常明显,而且占用电脑cpu较高,不是非常适用于爬虫.这篇博客中,我将介绍在爬虫中广泛运用的多线程+协程的解决方案,亲测 ...

随机推荐

  1. MVC5+EF6 入门完整教程2 :从前端UI开始

    MVC分离的比较好,开发顺序没有特别要求,先开发哪一部分都可以,这次我们主要讲解前端UI的部分. ASP.NET MVC抛弃了WebForm的一些特有的习惯,例如服务器端控件,ViewState这些东 ...

  2. 配置yum仓库:yum install 软件

    1.一个重要模板: 进入/etc/yum.repos.d文件夹,新建一个xiaoxu.repo文件,其中xiaoxu可以根据需要来取名. [模板] vim  xiaoxu.repo [rhel]    ...

  3. Linux上查看当前系统各内存分区信息

    命令 ulimit -a -a 查看所有信息,同理,也可以例如 ulimit -s 只查看栈占内存信息

  4. es7实现数学乘方

    //math.pow简写方法 console.log(2 ** 6)

  5. python中GraphViz's executables not found的解决方法以及决策树可视化

    出现GraphViz's executables not found报错很有可能是环境变量没添加上或添加错地方. 安装pydotplus.graphviz库后,开始用pydotplus.graph_f ...

  6. Bug搬运工-CSCux99539:Intermittent error message "Power supply 2 failed or shutdown"

    Description Symptom:Following error messages will be seen intermittently.%PFMA-2-PS_FAIL: Power supp ...

  7. Python socket day4

    TCP(较UDP麻烦但安全) 服务器和客户端区分的很明白 TCP客户端比起UDP多个连接服务器 TCP服务端 socket创建一个套接字 一定要绑定IP和端口,就跟110一样,是固定的让人随时能知道 ...

  8. yii2时区语言设置

    main.php return [ 'charset' => 'utf-8', 'language' => 'zh-CN', 'timeZone' => 'Asia/Shanghai ...

  9. 每日扫盲(二):xxx.dll文件的作用

    DLL,dynamic-link library 动态链接库.我们看他的说明,是应用程序扩展.DLL内是一些程序的功能.由于使用静态链接库(static LIBrary,LIB)会使主程序变得臃肿,并 ...

  10. 论STA | SOCV / POCV 之 variation (2)

    芯片制造涉及到许多复杂重复的过程,如:光刻.蚀刻.离子注入.扩散.退火.而且都是原子级操作,尽管控制非常严格,但偏差不可避免. 工艺偏差会导致芯片物理参数偏差,如:线宽.沟道掺杂浓度.线厚.临界尺寸. ...