在python(django)中,如何在更新全局字典数据结构时阻止访问?

2 投票
2 回答
780 浏览
提问于 2025-04-15 17:10

在Django中,当我想更新一个全局的字典数据结构时,我希望能锁住这个字典,以防不同的请求同时访问它。我打算写一个包装函数来更新和访问这个字典,并确保它的操作是同步的。我之前是用Java的,有什么建议吗?

2 个回答

1

一个有趣的选择是创建一个可以锁定的字典类,这个字典会根据调用者的执行环境自动锁定自己。:-)

Python的自省功能让这个变得可能——根据你的需求,这可能是个合适的方案。
不过,你需要在想要使用这个值的地方捕获可能出现的异常。
我不使用Django,所以不清楚请求是否使用线程——如果是的话(而且不是在单个线程上处理所有请求的异步响应),你可以在一段时间内替换掉引发的异常,使用一个“休眠-重试”的循环。

from inspect import stack

class DictLocked(Exception):
    pass

class LockableDict(dict):
    def __init__(self, *args, **kw):
        dict.__init__(self, *args, **kw)
        self.locked = False
        self.locker = None
    def start_update(self):
        print stack()
        self.locked = True
        #Holds the code frame responsible for locking
        self.locker = stack()[1][0]
    def finish_update(self):
        self.locked = False

    def __getitem__(self, item):
        print stack()
        if self.locked:
            if stack()[1][0] != self.locker:
                raise DictLocked("Dictionary locked")
        return dict.__getitem__(self, item)

    def __setitem__(self, item, value):
        if self.locked:
            if stack()[1][0] != self.locker:
                raise DictLocked("Dictionary locked")
        return dict.__setitem__(self, item, value)
2

在LockableDict这个例子基础上,稍微扩展一下,让它更强大一些,你可以使用真正的锁:

class LockableDict(dict):
    def __init__(self, *args, **kwargs):
        from threading import Lock
        self.lock = Lock()
        dict.__init__(self, *args, **kwargs)

    @property
    def locked(self):
        return self.lock.locked()

    def lock(self):
        self.lock.acquire()

    def unlock(self):
        self.lock.release()

# and then
my_dict = LockableDict({1:2, 3:4})
my_dict.lock()
# do modifications
my_dict.unlock()

撰写回答