为了提升程序运行速度
2、有哪些程序提速的方法: 3、python对并发编程的支持:(1)多线程:threading,利用CPU和IO可以同时执行的原理,让CPU不会干巴巴等待IO完成
(2)多进程:multiprocessing,利用多核CPU的能力,真正的并行执行任务
(3)异步IO:asyncio,在单线程利用CPU和IO同时执行的原理,实现函数异步执行
(4)使用Lock对资源加锁,放置冲突访问
(5)使用Queue实现不同线程/进程之间的数据通信,实现生产者-消费者模式
(6)使用线程池Pool/进程池Pool,简化线程/进程的任务提交、等待结束、获取结果
(7)使用subprocess启动外部程序的进程,并进行输入输出的交互
(1)多线程Thread(2)多进程Process(3)多协程Coroutine
5、CPU密集型计算/IO密集型计算(1)CPU密集型计算(CPU-bound):(bound指限制)
也叫计算密集型,是指I/O在很短的时间就可以完成,CPU需要大量的计算和处理,特点是CPU占用率高
例如 :压缩解压缩、加密解密、正则表达式搜索
(2)IO密集型计算(I/O-bound):
系统运行大部分的状况是CPU在I/O(硬盘/内存)的读/写操作,CPU占用率仍然很低
例如:文件处理程序、网络爬虫程序、读写数据库程序
(1)动态类型语言、边解释边执行
(2)GIL(全局解释器锁),无法利用多核CPU并发执行,单个时刻只能使用一个线程,所以慢。
是计算机程序设计语言解释器用于同步线程的一种机制,它使得任何时刻仅有一个线程在执行,即使在多核处理器上,使用GIL的解释器也只允许同一时间执行一个线程。
10、拥有GIL的python程序执行过程:(GIL锁遇到I/O操作会释放)thread1运行,此时拥有GIL锁,遇到I/O操作便释放GIL锁,此时thread2开始运行,加GIL锁,遇到I/O操作再释放GIL锁,thread3开始运行…
11、为什么设计GIL:为了解决多线程之间数据完整性和状态同步问题。简化了python对共享资源的管理。python中对象的管理,是使用引用计数器进行的,引用数为0则释放对象。
开始:线程A/B都引用了对象obj,obj.ref_num=2,线程A/B都想撤销对obj的引用。
(1)多线程threading机制用于IO密集型计算
因为在IO期间,线程会释放GIL,实现CPU和IO的并行,因此多线程用于IO密集型计算依然可以大幅提升速度
但是多线程用于CPU密集型计算时,只会更加拖慢速度。
(2)使用multiprocessing的多线程机制实现并行计算、利用多核CPU优势,为了应对GIL问题,python提供了multiprocessing。
(1)准备一个函数:
def my_func(a,b):
do_craw(a,b)
(2)怎样创建一个线程:
import threading
t=threading.Thread(target=my_func,args=(100,200)
#target是函数的名字,args里面是元组,是函数的参数
(3)启动线程:t.start() 等待结束:t.join()
(1)导入类库:import queue
(2)创建Queue:q=queue.Queue
(3)添加元素:q.put(item)
(4)获取元素:item=q.get()
(5)查询状态
查看元素的多少 :q.qsize()
判断是否为空:q.empty()
判断是否为满:q.full()
线程安全:某个函数、函数库在多线程环境中被调用时,能够正确地处理多个线程之间的共享变量,是程序功能正确完成
线程不安全:优于线程的执行随时会发生切换,就造成了不可预料的结果,出现线程不安全。
(1)try-finally模式
(2)with模式
(1)提升性能:因为减去了大量新建,终止线程的开销,重用了线程资源。
(2)使用场景:适合处理突发性大量请求或需要大量线程完成任务,但实际任务处理时间较短
(3)防御功能:能有效避免系统因为创建线程过多,而导致系统符合过大响应变慢等问题
(4)代码优势:使用线程池的语法吧自己新建线程执行线程更加简洁