python thread local,threading.thread python

  python thread local,threading.thread python

  在同一个进程下,多个线程共享进程的数据。为了保证数据的安全性,多线程写会被锁死,也就是说多线程模式下效率会降低。

  Threading.local()可以为每个线程创建一个本地名称空间。threading.local()是全局的,所有线程都可以访问,但是放入threading.local()对象的属性数据不会受到其他线程的干扰。

  threading.local实现线程数据隔离的主要原理是通过一个大字典,大字典的键值存储线程的id,值是一个小字典存储线程的局部变量组成的字典。

  知识储备:

  1.插槽__变量:

  实例化时__dict__属性受到限制,每次实例化都需要分配一个新的dict,所以大量实例化这个类存在空间浪费;如果一个类的属性被确定,它可以被__slots__变量限制。__slots__配置后,只能动态添加和修改__slots__中的属性,不能添加其他属性,所以没有__dict。

  https://blog.csdn.net/sxingming/article/details/52892640

  2.contextmanager上下文管理器

  从上下文库导入上下文管理器

  作为一个contextmanager,上下文管理器主要用来准备一些逻辑的执行,以及处理一些逻辑的善后工作。

  contextmanager主要实现了两个方法__enter__(在托管逻辑执行之前执行)和__exit__(在托管逻辑执行之后执行)。您可以直接定制这两个函数来实现定制的上下文管理器。

  使用contextmanager注释函数后,可以用。yeild之前的内容相当于__enter__,yelid之后的内容相当于_ _ exit _ _当函数遇到yield时,它在yield处停止,并返回yield后的值。执行完所有带的语句后,在yield之后执行语句。

  资源链接

  3、python弱引用weakref

  Python的垃圾收集主要使用引用计数、标记清除和世代回收机制;Python为每个对象维护一个引用计数器。当引用被创建或复制时,引用计数器为1,当对象被销毁时,引用计数器为-1。值为0意味着没有引用,这将释放内存。

  明确:解决循环引用问题。

  世代循环:以空间换时间,提高垃圾收集效率;生存时间越长,扫描间隔越长,减少频繁扫描造成的资源消耗。

  但是,通过调用weakref模块的ref来创建对象的弱引用不会生成引用计数,但是可以操作所指向的对象。

  https://www.cnblogs.com/goldsunshine/p/16307598.html

  threading.local()的源代码分析:

  Threading.local类使用一个_localimpl类作为每个线程的局部变量的管理类,用来以大字典的形式存储每个线程的局部变量;_localimpl的操作实际上是一个局部变量大字典的操作。

  _localiml线程管理类的主要功能是创建或获取线程局部变量的字典。

  # { id(Thread) - (ref(Thread),线程本地字典)}

  # id (thread 1):(ref(Thread),thread 1局部变量字典),

  class _localimpl:

  管理线程字典的类。

  # local()。_local__impl=_localimpl()

  # local()实例的attribute _local__impl是该类的一个实例。

  _local_impl只有这么多属性

  __slots__=key , dicts , localargs , locallock , __weakref__

  def __init__(self):

  # self.key线程对象中使用的键

  self.key=_threading_local。_localimpl。str(id(self))

  #大字典,格式{}

  # { id(Thread) - (ref(Thread),线程本地字典)}

  # id (thread 1):(ref(Thread),thread 1局部变量字典),

  self.dicts={}

  def get_dict(self):

  #从大字典self.dicts中获取线程局部变量字典

  thread=当前线程()

  返回self.dicts[id(thread)][1]

  def create_dict(self):

  #为当前线程创建一个线程局部变量字典

  localdict={}

  key=自我. key

  Thread=current_thread() #当前线程

  Idt=id(thread) #当前线程id

  def local_deleted(_,key=key):

  #定义一个弱引用的回调函数,在线程局部变量的管理类localimpl被删除时,从线程中删除相应的变量。

  thread=wrthread()

  如果线程不是无:

  德尔螺纹__dict__[key]

  def thread_deleted(_,idt=idt):

  # 定义一个弱引用的回调函数,当线程被删除时,在管理类localimpl对象的字典中删除该线程的字典项

  local=wrlocal()

  如果本地不为无:

  dct=local.dicts.pop(idt)

  # 定义两个弱引用

  wrlocal=ref(self,local_deleted)

  wrthread=ref(thread,thread_deleted)

  # 线程和局部变量管理类相互关联

  线程__dict__[key]=wrlocal

  #在字典中以线程编号为钥匙,保存了弱引用和线程局部变量的字典

  self.dicts[idt]=wrthread,localdict

  # { id(线程)- (ref(线程)),线程本地字典)}

  # id(线程1):(参考(螺纹),线程一局部变量字典),

  返回本地字典

  当地的类中通过__插槽_ _变量定义了两个变量本地__impl和_ _字典_,_本地_ _实现用来保存上述局部变量管理类_localimpl,dict__则保存当地的类自己的成员函数或变量,可以通过self.xxx来引用到当地。类中重载了__getattribute,setattr,_ _ delattr _ _等函数,通过重载这些函数,将当地的类中的__词典_ _对象指向了_本地_ _实现中保存的该线程的局部变量字典,对当地的类进行赋值和获取操作时,实际上是对_本地_ _实现中保存的该线程的局部变量字典进行操作。

  @上下文管理器

  def _patch(self): # self是本地()

  # 拿到本地()的属性_local__impl,_local__impl即是_localimpl()实例化的对象

  impl=对象. getattribute__(self, _local__impl )

  尝试:

  dct=impl.get_dict() #获取线程字典局部变量字典

  除了关键错误:

  dct=impl.create_dict() #抛出键错误,则创建线程局部变量字典

  args,kw=impl.localargs

  自我. init _ _(*参数,* *千瓦)

  with impl.locallock: #通过上下文方式加锁impl.locallock - Rlock()

  对象. self _ _ setattr _ _(self, __dict__ ,dct) #给本地()增加__词典_ _属性,指向线程小字典,即线程局部变量字典(指向字典,并非设置字典中的局部属性)

  产量

  本地类别:

  #本地()只有两个属性

  __slots__=_local__impl , __dict__

  def __new__(cls,/,*args,**kw):

  if(参数或千瓦)和(cls .__init__是对象. init__):

  引发TypeError(“不支持初始化参数")

  自我=对象. new__(cls) #父类目标创建类对象

  impl=_localimpl() # _localimpl实例化

  impl.localargs=(args,kw)

  impl.locallock=RLock()

  # 设置本地()属性_local__impl,赋值为_localimpl的实例化对象

  对象__setattr__(self, _local__impl ,impl)

  # 调用_localimpl的create_dict()函数创建小字典(线程局部变量字典)

  impl.create_dict()

  回归自我#返回配置好_本地_ _实现属性的本地()实例

  # 重载getattribute、setattr、delattr

  # getattribute、setattr、delattr操作loacl()实例,实际是操作

  # _localimpl,来对线程局部变量字典的操作

  def __getattribute__(self,name):

  带补丁(自身):#通过上下文管理准备数据

  返回对象. getattribute__(self,name) #通过上下文配置好本地()的__词典_ _中的数据后,直接到本地()的__词典_ _中拿

  def __setattr__(self,name,value):

  if name==__dict__: # local()的__词典_ _只读,不能设置和倒三角形

  引发属性错误(

  %r对象属性" __词典_ _ "是只读的

  %自我__类_ _ .__name__)

  带补丁(自身):

  返回对象__setattr__(自己,姓名,值)

  def __delattr__(self,name):

  if name==__dict__ :

  引发属性错误(

  %r对象属性" __词典_ _ "是只读的

  %自我__类_ _ .__name__)

  带补丁(自身):

  返回对象. delattr__(自己,名字)

郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。

留言与评论(共有 条评论)
   
验证码: