複数のスレッドが同じ要素をリストに2回追加しないようにするために、クラス内でロックを使用しています。しかし、クラス自体の中からロックで保護されたメソッドにアクセスしたい場合、クラスが止まってしまいます。既にロックされたコードブロックをクラスから呼び出すにはどうすればいいですか?
クラスは、この(それはもうあまり意味がありませんので、単純化)のようになります。
import threading
class List(object):
def __init__(self):
self.list = []
self.lock = threading.Lock()
def add(self, element):
print("adding")
with self.lock:
if not element in self.list:
self.list.append(element)
def get(self):
print("getting")
with self.lock:
# Try to get more elements, might fail
if len(self.list) == 0:
self.getFromDb()
if len(self.list) > 0:
el = self.list.pop()
return el
else:
return None
def getFromDb(self):
print("getting from db")
# Emulate an hardcoded database ;)
self.add("i am new")
# Here we will enter a block that is already locked by
# the thread who called get() so my method waits
# infinitely
それが新しい要素を追加したいとき、それが立ち往生ように、次のテストファイルは完了しません。リスト:
list = List()
print("= 1 =")
list.add("hi")
print("= 2 =")
print(list.get())
print("= 3 =")
print(list.get())
print("= 4 =")
出力は次のとおりです。
あり= 1 =
adding
adding
= 2 =
getting
hi
= 3 =
getting
getting from db
adding
あなたはそのすべてのメタを見ることができますodsは動作していますが、add
を再度呼び出すgetFromDb
(add
のロックされたブロックから呼び出された)から新しい要素を追加すると、アプリケーションを続行できません。
add
を使用せずにgetFromDb
に直接リストを入力する以外の方法はありますか? add
が重複をチェックしているので(これは非常に基本的な例です)、これは素晴らしいことではありません。
Lockの代わりにRLockをお探しですか? –