zoukankan      html  css  js  c++  java
  • Python的线程隔离实现方法

     前段时间看了下flask的源码,对于这样一个轻量级的web框架是怎样支持多线程的感到非常好奇,于是深入了解了一番。

    flask是依赖werkeug来实现线程间的隔离的,而werkeug最后又使用到了python的内置模块locals来承载数据,看不如写,于是自己实现了一下。

    from threading import currentThread, Thread
    from collections import defaultdict
    
    import sys
    
    
    class LocalProxy(object):
    
        def __init__(self):
            self.local = defaultdict(dict)
    
        def __repr__(self):
            return str(self.local)
    
        def __str__(self):
            return str(self.local)
    
        def __getitem__(self, item):
            return self.local[currentThread().ident][item]
    
        def __setitem__(self, key, value):
            self.local[currentThread().ident].update({key: value})
    
    print(sys.version)
    local_proxy = LocalProxy()
    print(local_proxy)
    
    local_proxy["main"] = "start"
    
    def change_property():
        local_proxy["main"] = "end"
    
    change_thread = Thread(target=change_property)
    change_thread.daemon= True
    change_thread.start()
    
    change_thread.join()
    
    print(local_proxy)

    输出:

    3.7.3 (default, Mar 27 2019, 17:13:21) [MSC v.1915 64 bit (AMD64)]
    defaultdict(<class 'dict'>, {})
    defaultdict(<class 'dict'>, {7092: {'main': 'start'}, 4892: {'main': 'end'}})

    这里是使用defaultdcit代替locals来作为数据承载的dict,然后使用currentThread方法获取当前线程id,以此作为key来实现各线程间的数据隔离。

    从输出可以看出,主线程设置了`main=start`后,子线程对该属性进行修改并未成功,而是在自己的线程id下创建了新的属性。

    实现过程中还发生了一个小插曲,当时的开启线程代码如下:

    change_thread = Thread(change_property)
    change_thread.daemon= True
    change_thread.start()

    报错:

    Traceback (most recent call last):
    3.7.3 (default, Mar 27 2019, 17:13:21) [MSC v.1915 64 bit (AMD64)]
    defaultdict(<class 'dict'>, {})
      File "E:/project/blog/blog/src/utils/local_.py", line 34, in <module>
        change_thread = Thread(change_property)
      File "D:UsersAdministratorAnaconda3lib	hreading.py", line 781, in __init__
        assert group is None, "group argument must be None for now"
    AssertionError: group argument must be None for now

    于是点开Thread源码看看这个group为何物:

        def __init__(self, group=None, target=None, name=None,
                     args=(), kwargs=None, *, daemon=None):
            """This constructor should always be called with keyword arguments. Arguments are:
    
            *group* should be None; reserved for future extension when a ThreadGroup
            class is implemented.

    原来Thread的初始化增加了group参数,切对其进行了断言,为以后即将实现的ThreadGroup铺路。

    ps: 以后传参还是尽量带上参数名。

  • 相关阅读:
    github for window的代理设置方法
    深入理解ANGULARUI路由_UIROUTER
    HTML:document.activeElement
    Ubuntu 安装java环境搭建
    svn 服务器搭建
    nginx tomcat 动静分离
    mysql5.5 修改字符集
    ansible 安装
    基于apache的tomcat负载均衡和集群配置
    数据库值错误怎么改?
  • 原文地址:https://www.cnblogs.com/xu-xiaofeng/p/13349312.html
Copyright © 2011-2022 走看看