python并发编程之进程池,线程池,协程

不能无限的开进程,不能无限的开线程,最常用的就是开进程池,开线程池。其中回调函数最重要。
回调函数其实可以作为一种编程思想,谁好了谁就去掉

只要你用并发,就会有锁的问题,但是你不能一直去自己加锁吧
那么我们就用QUEUE,这样还解决了自动加锁的问题
由Queue延伸出的一个点也非常重要的概念。以后写程序也会用到
这个思想。就是生产者与消费者问题

一、Python标准模块--concurrent.futures(并发未来)

1、concurrent.future模块是用来创建并行任务,提供了更高级别的接口,为异步执行调用。

2、concurrent.future这个模块用起来非常方便,它的接口也封装的非常简单

3、concurent.future模块既可以实现进程池,也可以实现线程池

4、模块导入进程池和线程池
from concurrent.futures import ProcessPoolExecutor,ThreadPoolExecutor
还可以导入一个Executor,但是你别这样导,这个类是一个抽象类
抽象类的目的是规范他的子类必须有某种方法(并且抽象类的方法必须实现),但是抽象类不能被实例化

5、
p=ProcessPoolExecutor(max_works)对于进程池如果不写max_works:默认的是cpu的数目,默认是4个
p=ThreadPoolExecutor(max_works)对于线程池如果不写max_works:默认的是cpu的数目*5

6、如果是进程池,得到的结果如果是一个对象。我们得用一个.get()的方法得到结果
但是现在用了concurent.future模块,我们可以用obj.result方法
p.submit(task,i) #相当于apply_async异步方法
p.shutdown() #默认有个参数wite=True (相当于close和join)

二、协程介绍

协程:单线程下实现并发(提高效率)

协程的使用场景:当程序中存在大量不需要CPU的操作时(IO),适用于协程

通俗的理解:在一个线程中的某个函数,可以在任何地方保存当前函数的一些临时变量等信息,然后切换到另外一个函数中执行,注意不是通过调用函数的方式做到的,并且切换的次数以及什么时候再切换到原来的函数都由开发者自己确定

协程和线程差异
  在实现多任务时, 线程切换从系统层⾯远不⽌保存和恢复 CPU上下⽂这么简单。 操作系统为了程
序运⾏的⾼效性每个线程都有⾃⼰缓存Cache等等数据,操作系统还会帮你做这些数据的恢复操作。
  所以线程的切换⾮常耗性能。但是协程的切换只是单纯的操作CPU的上下⽂,所以⼀秒钟切换个
上百万次系统都抗的住。

Greenlet模块和yield没有什么区别,就只是单纯的切,跟效率无关。
只不过比yield更好一点,切的时候方便一点。但是仍然没有解决效率。
Greenlet可以让你在多任务之间来回的切

Gevent介绍
Gevent是一个第三方库,可以轻松通过gevent实现并发同步或异步编程,在gevent中使用的主要模式是Greenlet
它是以C扩展模块形式接入python的轻量级协议。Greenlet全部运行在主程序操作系统进程的内部,但它们被协作式地调度。

其原理是当⼀个greenlet遇到IO(指的是input output 输⼊输出,⽐如⽹络、⽂件操作等)操作时,
⽐如访问⽹络,就⾃动切换到其他的greenlet,等到IO操作完成,再在适当的时候切换回来继续执⾏。

由于IO操作⾮常耗时,经常使程序处于等待状态,有了gevent为我们⾃动切换协程,就保证总有
greenlet在运⾏,⽽不是等待IO

重点:进程、线程、协程的应用场景

进程

进程是具有一定独立功能的程序关于某个数据集合上的一次运行活动,进程是系统进行资源分配和调度的一个独立单位。每个进程都有自己的独立内存空间,不同进程通过进程通信来通信。由于进程比较重量,占据独立的内存,所以上下文进程间的切换开销(栈、寄存器、虚拟内存、文件句柄等)比较大,但相对比较安全稳定

线程

线程是进程的一个实体,是cpu调度和分派的基本单位,它是比进程更小的能独立运行的基本单位。线程基本上不自己拥有系统资源,只拥有一点在运行中必不可少的资源(如程序计数器,一组寄存器和栈),但是它可以和同属一个进程的其他线程共享进程所拥有的全部资源。线程间的通信主要通过共享内存,上下文切换,资源开销较小,但是相比进程不够稳定容易丢失数据。

协程

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

应用场景
1、多进程:密集cpu任务,需要充分使用多核CPU资源(服务器,大量的并行计算)的时候,用多进程
缺陷:多个进程之间通信成本高,切换开销大

2、多线程:密集IO任务(网络IO,磁盘I/O,数据库I/O)使用多线程合适。
缺陷:同一个时间切片只能运行一个线程,不能做到高并行,但是可以做到高并发

3、协程:当程序中存在大量不需要CPU的操作时(IO),适用于协程
缺陷:单线程执⾏,处理密集CPU和本地磁盘IO的时候,性能较低。处理⽹络I/O性能还是⽐较⾼.

原文地址:https://www.cnblogs.com/lzf23/p/11652825.html