4

複数のスレッドで動作するメモ化デコレータを作成しようとしています。

スレッド間の共有オブジェクトとしてキャッシュを使用し、共有オブジェクトを取得/ロックする必要があることを理解しました。もちろん、スレッドを起動しています。

for i in range(5):
            thread = threading.Thread(target=self.worker, args=(self.call_queue,))
            thread.daemon = True
            thread.start()

労働者はどこにいますか:

def worker(self, call):
    func, args, kwargs = call.get()
    self.returns.put(func(*args, **kwargs))
    call.task_done()

もちろん、メモ関数で装飾された関数(このような)を同時に多くのスレッドに送信すると、問題が発生します。

メモのキャッシュをスレッド間の共有オブジェクトとして実装するにはどうすればよいですか?

4

1 に答える 1

2

最も簡単な方法は、キャッシュ全体に単一のロックを使用し、キャッシュへの書き込みが最初にロックを取得することを要求することです。

投稿したサンプルコードでは、31行目でロックを取得し、結果がまだ欠落していないかどうかを確認します。その場合は、先に進んで結果を計算してキャッシュします。このようなもの:

lock = threading.Lock()
...
except KeyError:
    with lock:
        if key in self.cache:
            v = self.cache[key]
        else:
            v = self.cache[key] = f(*args,**kwargs),time.time()

投稿した例では、関数ごとのキャッシュが辞書に保存されているため、関数ごとのロックも保存する必要があります。

ただし、非常に論争の多い環境でこのコードを使用している場合は、スレッドが同じことを計算していなくても、スレッドが互いに待機する必要があるため、許容できないほど非効率的です。キーごとのロックをキャッシュに保存することで、おそらくこれを改善できます。ただし、ロックストレージへのアクセスもグローバルにロックする必要があります。そうしないと、キーごとのロックを作成する際に競合状態が発生します。

于 2012-10-26T05:03:00.573 に答える