多线程:threading
,利用CPU和IO可以同时执行的原理,让CPU不会等到IO完成再执行;
多进程:multiprocessing
,利用多核CPU的能力,真正的并行执行任务;
异步IO:asyncio
,在单线程利用CPU和IO同时执行的原理,实现函数异步执行;
使用Lock
对资源加锁,防止访问冲突;
使用Queue
实现不同线程、进程之间的数据通信,实现生产者-消费者模式;
使用线程池Pool/进程池Pool,简化线程/进程的任务提交、等待结果、获取结果;
什么是CPU密集型计算、IO密集型计算?
- CPU密集型:CPU密集型也叫计算密集型,是指I/O在很短的时间就可以完成,CPU需要大量的计算和处理,特点是CPU占用率相当高;例如:压缩解压缩、加密解密、正则表达式搜索;
- I/O密集型:I/O密集型指的是系统运作大部分的状况是CPU在等I/O(硬盘、内存)的读/写操作,CPU占用率较低;例如:文件处理程序、网络爬虫程序、读写数据库程序;
多线程、多进程、多协程的对比
- 一个进程中可以启动N个线程,一个线程可以启动N个协程;
- 多进程Process(multiprocessing):
- 优点:可以利用多核CPU进行运算;
- 缺点:占用资源最多、可启动数目比线程少;
- 适用于:CPU密集型计算;
- 多线程Thread(threading):
- 优点:相比进程,更轻量级、占用资源少
- 缺点:
- 相比进程:多线程只能并发执行,不能利用多CPU(GIL);
- 相比协程:启动数目有限制,占用内存资源,有线程切换开销;
- 适用于:IO密集型计算、同时运行的任务数目要求不多;
- 多协程Coroutine(asyncio):
- 优点:内存开销最少、启动协程数量最多;
- 缺点:支持的库有限(aiohttp vs requests )、代码实现复杂;
怎样根据任务选择对应技术?
python速度慢的两大原因
- 动态类型语言,边解释边执行;
- GIL无法利用多核CPU并发执行;
GIL是什么
- 全局解释器锁(Global Interpreter Lock,缩写GIL)
- 是计算机程序设计语言解释器用于同步线程的一种机制,它使得任何时刻仅有一个线程在执行;
- 即便在多核处理器上,使用GIL的解释器也只允许同一时间执行一个线程。
为什么有GIL这个东西
- 为了解决多线程之间数据完整性和状态同步问题
- python中对象的管理,使用引用计数器进行的,引用数为0则释放对象
- GIL简化了python对共享资源的管理
怎样规避GIL带来的限制
- 多线程threading机制依然是有用的,用于IO密集型计算
因为在I/O(read,write,send,recv,etc.)期间,线程会释放GIL,实现CPU和IO的并行,因此多线程用于IO密集型计算依然可以大幅提升速度,但是多线程用于CPU密集型计算时,只会更加拖慢速度; - 使用multiprocessing的多进程机制是实现并行计算、利用多核CPU优势
为了应对GIL问题,python提供了multiprocessing