我有一个简单的服务器,可以进行按需镜像。获取是昂贵的(网络延迟,完整性检查,(重新)压缩等)。因此,我希望每个网址都有一个锁定,以便:
我最初做过类似的事情:
# Globals
fetching = dict()
fetch_lock = threading.Lock()
...
lock = None
do_fetch = False
with fetch_lock:
if url in fetching:
lock = fetching[url]
else:
lock = threading.Lock()
fetching[url] = lock
do_fetch = True
# Race condition
lock.acquire()
if do_fetch:
...
with fetch_lock:
lock.release()
if do_fetch:
del fetching[url]
# Serve file
...
竞争条件相当小(一个线程可能会尝试访问尚未在缓存中的文件),但我找不到解决方法。
答案 0 :(得分:1)
要解决这个问题,你可以抓住关键部分内的锁,如果你正在创建它(没有其他人会拥有它),如果锁已经存在,那么在关键部分之外获取它。
with fetch_lock:
if url in fetching:
lock = fetching[url]
else:
lock = threading.Lock()
fetching[url] = lock
do_fetch = True
lock.acquire()
if not do_fetch:
lock.acquire()
这将解决那里的竞争状况。虽然,我不明白的是为什么创建锁的线程将其从锁表中删除,然后你可以让一个线程在一个较新的线程获取它时为该文件提供服务。但那不是你问的。