在python(django)中,如何在更新全局字典数据结构时阻止访问?
在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()