深入理解Python&Werkzeug中的ThreadLocal变量

Python.ThreadLocal

我们知道多线程环境下,每一个线程均可以使用所属进程的全局变量。如果一个线程对全局变量进行了修改,将会影响到其他所有的线程。为了避免多个线程同时对变量进行修改,引入了线程同步机制,通过互斥锁,条件变量或者读写锁来控制对全局变量的访问。

只用全局变量并不能满足多线程环境的需求,很多时候线程还需要拥有自己的私有数据,这些数据对于其他线程来说不可见。因此线程中也可以使用局部变量,局部变量只有线程自身可以访问,同一个进程下的其他线程不可访问。

有时候使用局部变量不太方便,因此 python 还提供了 ThreadLocal 变量,它本身是一个全局变量,但是每个线程却可以利用它来保存属于自己的私有数据,这些私有数据对其他线程也是不可见的。

Werkzeug.ThreadLocal

Python通过 local 类来实现 ThreadLocal 变量,代码量不多(只有100多行),但是比较难理解,涉及很多 Python 黑魔法。那么 ThreadLocal 很牛逼了?  不!   Python 的 WSGI 工具库 werkzeug 中有一个更好的 ThreadLocal 实现,甚至支持协程之间的私有数据,实现更加复杂,功能更加强大。

Werkzeug 作为一个 WSGI 工具库,由于一些方面的考虑,并没有直接使用python内置的ThreadLocal类,而是自己实现了一系列Local类。包括简单的Local,以及在此基础上实现的LocalStack,LocalManager 和 LocalProxy。

Werkzeug 的设计者认为python自带的ThreadLocal并不能满足需求,主要因为下面两个原因:

  • Werkzeug 主要用“ThreadLocal”来满足并发的要求,python 自带的ThreadLocal只能实现基于线程的并发。而python中还有其他许多并发方式,比如常见的协程(greenlet),因此需要实现一种能够支持协程的Local对象。
  • WSGI不保证每次都会产生一个新的线程来处理请求,也就是说线程是可以复用的(可以维护一个线程池来处理请求)。这样如果werkzeug 使用python自带的ThreadLocal,一个“不干净(存有之前处理过的请求的相关数据)”的线程会被用来处理新的请求。

为了解决这两个问题,werkzeug 中实现了Local类。Local对象可以做到线程和协程之间数据的隔离,此外,还要支持清理某个线程或者协程下的数据(这样就可以在处理一个请求之后,清理相应的数据,然后等待下一个请求的到来)。

具体怎么实现的呢,思想其实特别简单,就是创建一个全局字典,然后将线程(或者协程)标识符作为key,相应线程(或协程)的局部数据作为 value。这里 werkzeug 就是按照上面思路进行实现,不过利用了python的一些黑魔法,最后提供给用户一个清晰、简单的接口。

asgiref.ThreadLocal

安装较高版本的django时随附了一个asgiref库,这个库看起来更高级,可以支持异步,但具体使用还有待后续研究。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值