当前位置:网站首页>【flask高级】结合源码分析flask中的线程隔离机制
【flask高级】结合源码分析flask中的线程隔离机制
2022-07-26 22:13:00 【馆主阿牛】
个人简介
- 作者简介:大家好,我是阿牛,全栈领域新星创作者。
- 博主的个人网站:阿牛的博客小屋
- 支持我:点赞+收藏️+留言
- 系列专栏:flask框架快速入门
- 格言:要成为光,因为有怕黑的人!

前些天发现了一个比较好的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。
点击跳转到网站:人工智能学习
前言
我们在前面的入门系列中写request对象时提到这个request其实是一个多线程机制,作为一个全局变量,他是如何做到多线程中各个线程互不影响,即线程安全的呢,这篇文章阿牛将结合源码剖析flask中的线程隔离机制!
问题引出
先在这里说明一下线程隔离,他指的是一个进程中的各个线程在运行时互不影响,像下面这段代码:
import threading
class B:
a = 0
b = B()
def func():
b.a += 1
print("线程1 : a = " + str(b.a) + "\n")
new_t = threading.Thread(target=func)
new_t.start()
b.a += 1
print("主线程 : a = " + str(b.a))

可以看到,a是全局变量,主线程和线程一对变量a的影响是相互的,不是隔离的,对应到flask中,request是一个全局变量,同一时间有可能接受很多网络请求,从而开启多个线程。为了让request正确的指向其实例化的Request对象,保证各个请求互不干扰,线程隔离机制就显得十分重要!接下来我们就来看看flask中的线程隔离机制!
flask中的线程隔离实现
按我们能想到的,我们可以用python中的字典这种数据结构来实现,像下面这样:
request = {
thread_id1:Request1;
thread_id2:Request2;
...
}
那么其实在flask内部也是类似的,也是用字典这种基本数据类型来实现线程隔离的,下面我们一起去看看吧!
字典只能保存数据,而我们还需要操作数据,因此需要将其封装到一个对象中,我们在入门系列中介绍到flask的核心之一是werkzeug,而我们要看的线程隔离的实现正好在werkzeug里面的local.py文件中:

可以看到有这样的一个Local对象,其实就是对字典原理的一个封装!
那么我们使用这个Local对象来试验一下线程隔离:
import threading,time
from werkzeug.local import Local
b = Local()
b.a = 0
def func():
b.a = 1
print("线程1 : a = " + str(b.a))
new_t = threading.Thread(target=func,name='thread_01')
new_t.start()
time.sleep(1)
b.a += 2
print("主线程 : a = " + str(b.a))

可以看到,我们用Local实例化的对象是线程隔离的!
接下来我们继续看之前画的这张图
之前写过_request_ctx_stack和_app_ctx_stack这连个变量实际上指向了LocalStack这个栈,即LocalStack实例化的对象!
那么现在我们看完Local之后,我们也从名字猜想这个LocalStack不简单,他是一个线程隔离的栈!
我们可以看看LocalStack的源码:
可以看到LocalStack对线程隔离对象Local进行了封装,并且提供了push,pop,以及取栈顶元素的top方法!
看到这我们总结一下就是:Local使用字典的方式实现了线程隔离,LocalStack对Local进行了封装形成了线程隔离的栈!
依旧用LocalStack写个案例看看:
import threading,time
from werkzeug.local import LocalStack
myStack = LocalStack()
myStack.push(1)
print("在主线程push后,值为:" + str(myStack.top))
def fun():
# 线程一
myStack.push(2)
print("在线程一push后,值为:" + str(myStack.top))
new_t = threading.Thread(target=fun,name='thread_01')
new_t.start()
time.sleep(1)
#主线程
print("最后主线程的值为 :" + str(myStack.top))

可以看到线程之间也是互不影响的!
所以说flask中AppContext和RequestContext也是线程隔离的(因为这两个上下文被推入了LocalStack),本质上就是当使用到request时,线程隔离使得request能够正确找到其实例化的Request!
总结
使用线程隔离意义在于:使当前线程能够正确引用到他自己所创建的对象,而不是引用到其他线程所创建的对象!
由此来推:
不仅request是线程隔离的,session和g对象也是(注意:flask的核心对象app不是线程隔离的,全局只有一个,也就是current_app的线程隔离是没有意义的!而request的实例化对象Request有很多个!)
结语
如果你觉得博主写的还不错的话,可以关注一下当前专栏,博主会更完这个系列的哦!也欢迎订阅博主的其他好的专栏。
边栏推荐
- Monte Carlo search tree (UCT) based on confidence upper bound to realize four sub chess
- what crlf mean
- 逆袭黑马:数据库全栈工程师(DevDBOps)培训,把最好的课程送给您!
- Embedded SIG | 分布式软总线
- 【HCIP】OSPF 特殊区域、汇总、认证
- Shardingsphere JDBC keyword problem
- Page file system based on C language
- Do you know the common core types of magnetic ring inductors?
- [hcip] OSPF relationship establishment
- Cloud native microservices Chapter 1 server environment description
猜你喜欢

Shardingsphere JDBC keyword problem

面试:你印象最深的BUG,举个例子

nvidia-smi报错:NVIDIA-SMI has failed because it couldn‘t communicate with the NVIDIA driver 完整记录

Linear DP of dynamic programming

Plato Farm有望通过Elephant Swap,进一步向外拓展生态

Eureka基本使用

Plato farm is expected to further expand its ecosystem through elephant swap

Arduino实验一:双色灯实验

App information reconnaissance & night God simulator burp packet capture configuration
What if redis memory is full? This is the right way to deal with it
随机推荐
[paper reading] logan:membership influence attacks against generative models
【MySQL】CentOS 7.9安装、使用MySQL-5.7.39二进制版
『Mysql』汇总Mysql索引失效的常见场景
Arduino experiment I: two color lamp experiment
Plato Farm有望通过Elephant Swap,进一步向外拓展生态
kalibr标定realsenseD435i --多相机标定
7.27 watch first | openeuler is ambitious, open source Huizhi creates the future - the most detailed agenda of the Euler sub forum of the open atom global open source summit is released
what is qrc in qt
what is a kit in qt
芯鼎收购紫光控股!万业企业:全面转型集成电路!
nvidia-smi报错:NVIDIA-SMI has failed because it couldn‘t communicate with the NVIDIA driver 完整记录
[untitled]
The secret weapon of apple iphone11 series: U1 chip may usher in the era of ultra wideband
sql多表查询的练习
DTS is equipped with a new self-developed kernel, which breaks through the key technology of the three center architecture of the two places Tencent cloud database
《强化学习周刊》第55期:LB-SGD、MSP-DRL & 对抗鲁棒强化学习
Day07 MySql知识点再总结与多表查询
Implementation principle of semaphore in golang
STM32-如何使用串口
what is qrc in qt