0

我有一个执行按需镜像的简单服务器。获取成本很高(网络延迟、完整性检查、(重新)压缩等)。因此,我希望每个 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
...

竞争条件相当轻微(一个线程可能会尝试访问尚未在缓存中的文件),但我找不到解决它的方法。

4

1 回答 1

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()

这将解决那里的竞争条件。虽然,我不明白为什么创建锁的线程将它从锁表中删除,然后你可以让一个线程在一个较新的线程获取它时为文件提供服务。但这不是你问的。

于 2012-04-16T17:50:37.063 回答