网站网站建设公,网站模板建设报价,温州网站系统开发,php网站集成支付宝接口通过学习bi站 蚂蚁学Python 老师视频总结文档#xff0c;仅用于学习。。。
python进程、线程、协程 多线程#xff1a;threading#xff0c;利用CPU和IO可以同时执行的原理#xff0c;不会让CPU干巴巴的等待IO完成 多进程#xff1a;multiprocessing#xff0c;利用多核…通过学习bi站 蚂蚁学Python 老师视频总结文档仅用于学习。。。
python进程、线程、协程 多线程threading利用CPU和IO可以同时执行的原理不会让CPU干巴巴的等待IO完成 多进程multiprocessing利用多核CPU的能力真正的并行执行任务 异步IOasyncio在单线程利用CPU和IO同时执行的原理实现函数异步执行
方法 使用Lock对资源加锁防止冲突访问锁起来就可以实现有序访问 使用Queue实现不同线程/进程之间的数据通信实现生产者—消费者模式 使用线程池Pool/进程池Pool简化线程/进程的任务提交、等待结束、获取结果 使用subprocess 启动外部程序的进程并进行输入输出交互
1. CPU密集型计算、IO密集型计算
1.1 CPU密集型(CPU-bound) CPU密集型也叫计算密集型是指在I/O在很短的时间就可以完成CPU需要大量的计算和处理特点是CPU占用率相当高 例如 压缩和解压缩加密解密正则表达式搜索 1.2 IO密集型(I/O-bound) IO密集型是指是系统运作大部分的状况是CPU在等I/O (硬盘/内存) 的读/写操作CPU占用率仍然较低 例如 文件处理程序大量读写程序网络爬虫程序大量网络下载网络下载占用很长时间读写数据库程序网络的读取网络开销比较多 2. 多进程、多线程、多协程的对比
2.1 多进程(multiprocessing) 优点可以利用多核CPU并行运算 缺点占用资源最多、可启动数目比线程少 适用于CPU密集型计算 一个进程可以启动N个线程
2.2 多线程(threading) 优点相比进程更轻量级、占用资源少 缺点 相比进程多线程只能并发执行并不能利用多CPUGIL相比协程启动数目有限制占用内存资源有线程切换开销 适用于IO 密集型计算、同时运行的任务数目要求不多 一个线程可以启动N个协程
2.3 多协程(Coroutine - asyncio)
优点内存开销最少、启动协程数量最多缺点支持的库有限制、代码实现复杂适用于IO密集型计算、需要超多任务运行、但有现成库支持的场景
3. Python 的GIL
python慢的原因 动态类语言边解释边执行GIL的存在导致python无法利用多核CPU并发执行 3.1 GIL是什么
全局解释器锁Global Interpreter Lock
是计算机程序设计语言解释器用于 同步线程的一种机制它使得任何时刻仅有一个线程在执行
即便在多核处理器上使用GIL的解释器也只允许同一时间执行一个线程。 即使电脑有多核CPU单个时刻也只能使用一个相比较于并发加速的C/Java慢很多 3.2 GIL 存在的原因
Python设计初期为了规避并发问题引入了GIL现在想去除却去除不掉了
引入GIL的原因: 为了解决线程之间数据完整性和状态同步问题 Python中对象的管理是使用引用计数器进行的引用数为0则释放对象 例线程A和线程B都引用的对象objobj.ref_num 2假如线程A和线程B都想撤销对obj的引用 GIL的好处简化了python对共享资源的管理
3.3 规避GIL带来的限制 1、多线程 threading 机制 还是有用的用于IO密集型计算 因为在 I/O read、write、send、recv、etc.期间线程会释放 GIL , 实现CPU和IO并行因此 多线程用于IO密集型计算依然可以大幅度提升速度 但是多线程用于CPU密集型计算只会拖慢速度 2、使用 multiprocessing 的多进程机制实现并行计算、利用多核CPU优势为了应对GIL的问题Python提供了multiprocessing 3.4 并发与并行
并发
指的是任务数多余cpu核数通过操作系统的各种任务调度算法实现用多个任务“一起”执 行实际上总有一些任务不在执行因为切换任务的速度相当快看上去一起执行而已
并行
指的是任务数小于等于cpu核数即任务真的是一起执行的。
4. 线程
4.1 创建多线程的方法 1、准备一个函数 def my_func(a,b)do_sum(a,b)2、怎样创建一个线程 import threading
t threading.Thread(targetmy_func, args(100,200)) # target 表示要执行的任务(传入函数名)args表示传入函数的参数3、启动线程 t.start()4、等待结束 t.join()4.2 单线程与多线程对比
import blog_spider
import threading
import time# 单线程
def single_thread():print(single_thread begin)for url in blog_spider.urls:blog_spider.craw(url)print(single_thread end)# 多线程
def multi_thread():print(multi_thread begin)threads []for url in blog_spider.urls:threads.append(threading.Thread(targetblog_spider.craw, args(url,)))for thread in threads:thread.start() # 开启线程for thread in threads:thread.join() # 等待线程结束print(multi_thread end)if __name__ __main__:start time.time() # 开始时间single_thread()end time.time() # 结束时间print(single thread cost:, end-start, seconds) # single thread cost: 8.59098196029663 secondsstart time.time()multi_thread()end time.time()print(multi thread cost:, end - start, seconds) # multi thread cost: 0.82523512840271 seconds4.3 多线程生产消费模式
4.5 线程池
4.5.1 线程池的原理
线程的生命周期 新建线程系统需要分配资源、终止线程系统需要回收资源如果可以重用线程则可以减去新建/终止的开销 4.5.2 使用线程池的好处
提升性能因为减去了大量新建、终止线程的开销重用了线程资源适用场景适合处理突发性大量请求或需要大量线程完成任务、但实际任务处理时间较短防御功能能有效避免系统因为创建线程过多而导致系统负荷过大响应变慢等问题代码优势使用线程池的语法比自己新建线程执行线程更加简洁