オンデマンドのミラーリングを行う単純なサーバーがあります。フェッチは高価です (ネットワーク遅延、整合性チェック、(再) 圧縮など)。したがって、フェッチされる URL ごとに 1 つのロックを設定したいので、次のようにします。
- 1 つのファイルをフェッチするスレッドは 1 つだけです。
- 別のスレッドが現在フェッチされているファイルの 1 つを必要とする場合、ファイルの準備ができるまでブロックされます。
私は当初、次のようなことをしていました:
# 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
...
競合状態はかなりマイナーですが (スレッドがまだキャッシュにないファイルにアクセスしようとする可能性があります)、それを解決する方法が見つかりません。