在CPython解释器中,同一个进程下开启的多线程,同一时刻只能有一个线程执行,无法利用多核优势
GIL本质是一把互斥锁,保护不同的数据的安全,应该加不同的锁
所有数据都是共享的,代码作为一种数据也是被所有线程共享,所有线程的任务,都需要将任务的代码当做参数传给解释器的代码去执行
GIL保护的是解释器级的数据保护自己的数据需要自己加锁处理
GIL的存在使得同一时刻统一进程中只有一个线程被执行,因为CPython的内存管理机制非线程安全的,很多其他的特性依赖于GIL,所以即使它影响了程序效率也无法去除
在CPython中,GIL会把线程的并行变成串行,导致效率降低
每当执行一个文件,就会启动一个python解释器
py文件中的内容本质都是字符串,只有在被解释器解释时,才具备语法意义,解释器会将py代码翻译为当前系统支持的指令交给系统执行
有了GIL后,多个线程将不可能在同一时间使用解释器,从而保证了解释器的数据安全
GIL的解锁与解锁时机
加锁的时机:在调用解释器时立即加锁
解锁时机:
当前线程遇到了IO时释放
当前线程执行时间超过设定值时释放,解释器会检测线程的执行时间,一旦到达某个阈值,通知线程保存状态切换线程,以此来保证数据安全
多线程用于IO密集型,如socket,爬虫,web
多进程用于计算密集型,如金融分析
Pool可以提供指定数量的进程,供用户调用,当新的请求提交到pool中时,池未满,就会创建一个新的进程来执行该请求,如果池中进程数已经达到最大值,那么该请求就会等待,直到池中有进程结束就重用进程池中的进程
方法:close()关闭进程池
get()返回结果
ready()如果调用完成,返回True
successful()如果调用完成且没有引发异常,返回True,如果在结果就绪之前调用此方法,引发异常
wait()等待结果变为可用
terminate()立即终止所有工作进程,,同时不执行任何清理或结束任何挂起工作
进程池,默认参数为cpu核心数*1
线程池,默认参数为cpu核心数*5
阻塞 非阻塞
程序遇到了IO操作,无法继续执行代码,叫做阻塞
程序没有遇到IO操作,正常执行中,就叫非阻塞
他们是指程序运行的状态
就绪 运行 阻塞
同步 异步
同步(调用/执行/任务/提交),发起任务后必须等待任务结束,拿到一个结果才能继续运行
异步 发起任务后不关心任务的执行过程,可以继续往下运行
异步效率高于同步
但是并不是所有任务都可以异步运行,哦按段任务是否可以异步的条件是,任务发起方是否立即需要执行结果
同步不等于阻塞,异步不等于非阻塞
当使用异步方式发起任务时,任务中可能包含io操作,异步也可能阻塞
同步提交任务可能需要时间,但是不等于阻塞
线程池方法:
submit()以异步的方式提交任务
result()是阻塞的,会等到任务执行完成才继续执行会异步变成同步
shutdown()是一个阻塞函数,会等到线程池所有任务完成后继续执行
进程池/线程池
本质是一个存储进程或线程的列表