concurrent.futures提供了使用线程或进程工作池(pools of workers)来运行任务的接口。这个API使得多线程和多进程并发变得非常类似。它是在threading和multiprocessing接口上的封装。
Executors被用来管理工作池;futures被用来管理workers运行的结果。 ———————————————— 原文链接:https://blog.csdn.net/qq_16912257/article/details/79661863
- 多进程:进程是拥有资源的基本单位,其拥有独立的堆空间和栈空间。由操作系统调用。
- 多线程:线程是独立调度的基本单位,线程不拥有资源,但可以访问其隶属进程的资源。线程共享堆空间,拥有独立的栈空间。由操作系统调用。
- 协程:协程又叫微线程,是将线程切割成多段执行,可以随时暂停,由程序员控制。协程的效率比多线程高,因为其不需要进行竞争和切换,同时使用多路复用来同时管理多个接口的请求。
GIL(全局解释器锁):是只有CPython解释器中才有的线程锁。一个进程中只有一个GIL,一个线程只有获取了GIL才能执行,GIL释放后需要线程间的竞争和切换,使得Python的多线程反而耗时。
- 管道:管道是半双工的,要双向通信必须建立两个管道;
- 消息队列:进程同时维护消息队列,通过写消息和读消息进行通信;
- 共享内存:进程间共享内存,类似于线程共享进程的堆空间,可以直接通过数据的读写进行通信。
多路:多个连接,复用:一个或少量线程,即利用一个或少量的线程来同时管理多个连接。在一个或少量的线程中不停查看多个接口的状态,其中任何一个任务完成IO就去执行它。
- select:轮询多个任务,任何一个完成了IO就去执行后续操作。限制最多同时监视1024个接口;
- poll:同select,但是取消了1024的限制;
- epoll:不再轮询,而是使用回调来通知状态。
- 并发:在一段宏观的时间上多个任务同时执行,实际上是分时间片轮转执行。
- 并行:多核的条件下,同一时刻两个及以上进程同时执行,进程间互不抢占资源。
将线程2作为参数传递到线程1并调用。
import threading
def fun1(t2):
print('running fun1')
t2.start()
def fun2():
print('running fun2')
if __name__ == '__main__':
t2 = threading.Thread(target=fun2)
t1 = threading.Thread(target=fun1, args=(t2,))
t1.start()
同步与异步:主要关注消息通信机制。 • 同步就是在发出一个调用之后,调用没有得到结果之前该调用不返回。即同步是主动等待消息。 • 异步调用不会等待结果而是立即返回,然后等待被调用者使用消息、通知或者回调函数来通知调用者。即异步是被动接收消息。
阻塞与非阻塞:主要关注程序在等待时的状态。 • 阻塞是指程序在等待结果的时候被挂起,不能去完成别的任务【浪费时间】; • 非阻塞是指程序在等待的过程中可以做别的事情【需要切换开销】。
因此,异步非阻塞是当进程提交一个请求,不需要等到返回结果,可以直接回去干别的事情。也不需要时不时来轮询一下完成了没有,只需要好好做自己的事等着回调来告诉他任务完成了。
- 问题:python多线程中,每个线程使用局部变量时,局部变量不会相互影响。但当多个线程处理全局变量时,这个全局变量是共享资源,线程之间相互干扰导致结果错误。
- 解决:Python提供了 threading.local 类,将这个类实例化得到一个全局对象,但是不同的线程使用这个对象存储的数据其它线程不可见(本质上就是不同的线程使用这个对象时为其创建一个独立的字典)。