程序多线程并发
目的
- 提高程序运行的速度
程序提速的方式
- 单线程串行
- 多线程并发
- 多 CPU 并行
- 多机器并行
python 运行效率低下原因
-
动态类语言,边解释边执行;
-
不需要定义数据类型,Python 判断数据类型也会降低执行效率
-
GIL(global interpreter lock;全局解释器锁)
GIL :序设计语言解释器用于同步线程的一种机制,使得任何时刻仅有一个线程在执行。即便在多核处理器上,使用 GIL 的解释器也值允许一同时一个时间执行一个线程。
如何规避 GIL 的限制
- 多线程机制依旧是有用的,用于 I/O 密集型计算,因为 I/O 期间线程会释放 GIL,实现 CPU 和 I/O 之间的并行,因此多线程用于 CPU 的密集型计算时,只会更加拖慢速度;
- 使用multiprocessing 的进程机制实现并行计算,利用多核 CPU 优势,因此对 GIL 问题,Python 提供了 multiprocessing
Python 对并发编程的支持
1. 多进程
porcess,multiprocessing
- 一个进程中可以有多个线程,
- 可用资源最多,但可以启动的数据比线程少
- 适用于 CPU 密集型计算
2. 多线程
thread
- 占用资源少
- 相比进程:多线程只能并发执行,不能利用多 CPU(GIL)
- 相比协程:启动数目有限,占用内存职员,有线程切换的开销
- 适用于 I/O密集型,同时运行的任务数目不能太多
3. 多协程
coroutine,asyncio
- 一个线程具有多个协程
- 内存开销最小,启动协程数量最大
- 支持的库有限(aiohttp vs request),代码实现复杂
- 适用于 I/O 密集型,同时运行的任务数目可以很大
CPU 密集型计算 vs I/O 密集型计算
CPU 密集型:CPU-bound
- 限速就是 CPU,CPU 需要大量计算和处理,CPU 占用率高
- 压缩和解压缩、加密和解密、正则表达式搜索 IO 密集型:I/O-bound
- CPU 占用率低
- 文件处理程序、网络爬虫程序、读写数据库程序
4. 其他
- 异步 I/O
- 使用 lock 对资源加锁,房子冲突访问
- 使用 queue 实现对不同线程\进程之间的数据通信,实现生产者消费者模式
- 使用线程池\进程池,来简化线程\进程的任务提交,等待结果和获取结果
- 使用 subprocess 启动外部程序的进程,并进行输入输出交互