5.2 Python和Flask的多线程

python不能充分利用多核CPU的优势:

因为python有一个全局解释器锁GIL(Global Interceptor Lock),这个全局解释器锁会不管有多少个核,我们一个进程有多少个线程,都限制了同一时间只能在一个核上运行一个线程。

为了解决线程安全问题引用了锁,python中有两种锁

  • 细粒度锁:由程序员手动加锁

  • 粗粒度锁:有python在解释器上加锁,同一时间只能运行一个核。

python有很多全局解释器,如cpython和jpython。GIL只是加在最常见的cpython上的,所以使用jpython可以去掉这个限制。

也可以采用多进程的方式来解决这个问题,但是这样会带来其他的问题,如多进程通信技术,进程切换带来的开销等

python的多线程到底是不是鸡肋

我们的程序从一个时间段内最多的操作类型,可以分类IO密集型和CPU密集型

  • IO密集型:一个时间段内,查询数据库,请求网络资源,读写文件等操作居多的,则属于IO密集型。

  • CPU密集型:一个时间段内,严重依赖CPU计算资源的操作(如圆周率的计算)非常多,则属于CPU密集型。

而我们大部分的编程都是IO密集型的,对于IO密集型的程序来源,Python的多线程是有意义的,例如在进行一个数据库查询的时候,大部分的时间都是在等待结果返回,等待的这段时间并不消耗CPU的资源,不如让给其他线程去执行。

flask的多线程以及问题

  • flask内置了webServer服务器,一般在生产环境会替换掉这个默认的服务器

  • flask内置的webServer服务器默认是使用单进程单线程的方式执行的,多个请求进来必须要一个一个的执行,不能同时执行,这是因为自己调试大部分情况下单进程单线程就足够了。

  • 如果要开启多线程模式,只需要在运行Flask核心app对象的时候,设置关键字参数threaded=True即可。如果要开启多进程,将processes设置为True即可。

  • 观察Flask多线程模式 的技巧 在新版pycharm上,启用debug模式(是工具的debug,不是Flask的debug),在视图函数上打一个断点,然后再浏览器上发多次请求,可以看到,处理每个请求的线程不一样

  • Flask在单线程的时候,request永远都指向的是为了处理当前请求而实例化的Requset对象,这没有问题;在多线程的时候,由于request只是一个变量,但是多个线程处理多个请求,就会实例化不同的Request对象,在某一时刻request变量指向哪一个Request对象是不确定的,这时候,如果在代码中获取request并且视图修改的话就会遇到问题

Last updated