day34 GIL锁 线程队列 线程池
一、Gil锁(Global Interpreter Lock)
python全局解释器锁,有了这个锁的存在,python解释器在同一时间内只能让一个进程中的一个线程去执行,这样python的多线程就无法利用多核优势,但是这并不是python语言本身的缺点,是解释器的缺点,这个问题只存在于Cpython解释其中,像Jpython就没有。但是Cpthon是python官方解释器(算目前运行效率最高的吧),所以多数人都以为Gil锁是python语言的弊端。
#GIL锁图解
过程解释:
1、加载python解释器代码
2、加载自己的py文件
3、py文件作为参数传给解释器(因为有GIL锁,一次只能一个线程进入)
4、解释器将py文件编译成.pyc字节码文件
5、解释器通过虚拟机将字节码文件转为二进制文件
6、二进制文件等待cpu调用
二、线程队列
import queue
线程队列有三种形式
1、先进先出
q = queue.Queue(3) 创建一个长度为3的队列,先进先出
q.put()
q.get()
q.size() #当前队列中有多少个元素
2、后进先出
q = queue.LifoQueue(3) 创建一个长度为3的后进先出队列
3、优先级队列
q = queue.PriorityQueue(3) 创建一个长度为3的优先级队列
1 import queue 2 # q = queue.Queue() 3 # q =queue.LifoQueue() 4 q = queue.PriorityQueue() #优先级队列 5 # put里是一个元组,元组的一个元素代表优先级(通常是数字,也可以是非数字,数字越小,优先级越高),第二个元素是存入队列中的值 6 #一个队列中,优先级必须是同一种数据类型,才能比较,否则会报错 7 # 如果优先级相同,那么按照后面值的ASCII码的顺序来排序 8 #优先级相同的数据,他们后面的值必须是相同的数据类型才能比较,但优先级相同的两个字典无法比较 9 10 # q.put((-1,'ca')) #优先级相同的两个字符串,逐个比较ASCII码值 11 # q.put((-1,'cb')) 12 13 # q.put(("a","d")) #优先级为非数值类型 14 # q.put(('b',"c")) 15 16 # q.put((1,{1:'hh',2:'ss'})) #优先级相同的两个字典,无法比较,报错 17 # q.put((1,{3:'dd',4:'jj'})) 18 19 q.put((2,(4,5))) #优先级相同的元组,逐个比较元组元素值 20 q.put((2,(4,4))) 21 22 print(q.get()) 23 print(q.get())
三、concurrent.futures模块
通过这个模块可以创建和使用线程池和进程池
格式
from concurrent.futures import ThreadPoolExecutor, ProcessPoolExecutor
t = ThreadPoolExecutor(max_workers=4) #创建一个线程池对象,容量为4
方法:
t.submit(fun,*args,*kwargs) #异步提交任务
res= t.submit(fun,*args,*kwargs) #返回值是一个对象
res.result() #从对象中取值,会等待任务的执行结果,等不到是阻塞
t.shutdown) #等待已提交任务完成,相当于close()和join()的效果
t.map(fun, iter) #异步提交任务
res = t.map(fun, iter) #返回结果是一个生成器对象
for el in res: #取值
print(el)
add_done_callback(fun2) #添加回调函数
t.submit(fun1,参数).add_don_callback(fun2) #调用回调函数语法