我有一个执行按需镜像的简单服务器。获取成本很高(网络延迟、完整性检查、(重新)压缩等)。因此,我希望每个 url 获取一个锁,这样:
- 只有一个线程会获取一个文件;
- 如果另一个线程想要当前正在获取的文件之一,它将阻塞直到文件准备好。
我最初虽然想做类似的事情:
# 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
...
竞争条件相当轻微(一个线程可能会尝试访问尚未在缓存中的文件),但我找不到解决它的方法。