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: 以后传参还是尽量带上参数名。

原文地址:https://www.cnblogs.com/xu-xiaofeng/p/13349312.html