python中本地线程ThreadLoc
关于本地线程(线程本地变量,线程本地存贮),如果你之前有使用过Flask框架,肯定会好奇,为什么在多线的模式的情况,每个线程都能保留自己一份独立的参数,而不会被其他线程的参数影响,(每个请求上下文中都有自己的内容)。
理论来说对于(单核多线程模式下)FlaskWeb应用来说,每一个请求就是一个独立的线程。请求之间的信息要完全隔离,避免冲突,这就需要用到ThreadLocal。ThreadLocal中每一个变量中都会创建一个副本,每个线程都可以访问自己内部的副本变量。
比如:flask中我们的一个HTTP请求,都能保持独立自己的参数信息,flask中全局变量改为dict,每一个线程都有对应的自己的key,并将request作为value存放,
PS:通常我们的flask运行的是,一般有几个模式
单进程单线程多进程多线程单进程多线程单进程多协程但是在我们的ThreadLocal对于协程的方式是不支持的!后续再梳理一下,在flask中,听闻作者是自己自定义一个Local用于对协程的支持!(比较我们的并发模式有很多种)下我们的Local一些知识点。
PS:python自带的ThreadLocal只能实现基于线程的并发
关于ThreadLocal在python中一个ThreadLocal是一个全局变量,但是它是一种特殊的对象,它的状态对线程隔离。
一个线程中的局部变量只有线程自身可以访问,同一个进程下的其他线程不可访问,每个线程都只能读写自己线程的独立副本,这样可以做到线程隔离,做相关数据防污染!这样就可以利用它来保存属于线程自己内部的私有数据。
意思就是:每个线程对一个ThreadLocal对象的修改都不会影响其他的线程。
ThreadLocal对象实现原理:以线程的ID来保存多份状态字典。
PS:当然也可以改为我们的协程的!指需要内部改为协程的ID!
简单示例:
importthreading#获取ThreadLocal对象local_storage=threading.local()local_storage.number=local_storage.request="请求对象"print(初始化,local_storage.number)print(初始化,local_storage.request)#定义修改变量的线程classTestThread(threading.Thread):defrun(self):print(开始修改local_storage.number)local_storage.number=02print(开始修改local_storage.request)local_storage.request="我是线程内独立的一个请求对象"importtimetime.sleep(1)print(local_storage.number)print(local_storage.request)print(""*20)another=TestThread()another.start()#打印2another.join()print(在主线程里面的值并没有被修改:,local_storage.number)#但是在主线程里面的值并没有被修改打印1print(在主线程里面的值并没有被修改:,local_storage.request)#但是在主线程里面的值并没有被修改打印1
输出结果为:
初始化初始化请求对象开始修改local_storage.number开始修改local_storage.request02我是线程内独立的一个请求对象在主线程里面的值并没有被修改:在主线程里面的值并没有被修改:请求对象
自己模拟顶一个类似的ThreadLocal,之前,关于字节码执行的是,其实我们的了解到过了关于python字典是否是线程安全的问题。
如果验证字典是否是线程的安装的,主要是看原子操作,写操作的是否分多个STORE_SUBSCR字节码。
分析字典的添加是否是线程安全显示acton()的反汇编:
storage={}defacton():globalstoragestorage={"xiaozhong",}importdisdis.dis(acton)
输出的结果为:
LOAD_CONST1(xiaozhong)2LOAD_CONST2()4BUILD_SET26STORE_GLOBAL0(storage)8LOAD_CONST0(None)10RETURN_VALUE
字节码指令参考
转载请注明:http://www.sonphie.com/lcbx/14489.html