スレッドを使用する2つのクラスがあると仮定します
class foo(threading.Thread):
def __init__(self):
threading.Thread.__init__(self,name="foo=>bar")
self.var1 = {}
def run(self):
while True
value, name = getvalue() // name is an string
self.var1[name] = value
bar(self)
class bar(threading.Thread):
def __init__(self,fooInstance):
threading.Thread.__init__(self,name="bar")
def run(self):
while True
arg = myfunction() // somefunction (not shown for simplicity)
val = myOtherfunction(fooInstance.var1[arg]) //other function
print(val)
f = foo()
f.start()
の変数var1
はfoo
時間の経過とともに変化するため、bar
これらの変化に注意する必要があります。それは私には理にかなっていますが、最終的に失敗する可能性のある基本的な何かがここにあるのではないかと思います。これはPythonで正しいですか?
実際の共有部分は、「他のオブジェクトと値を共有するにはどうすればよいですか?」と同じ質問です。スレッドなしで、すべて同じソリューションが機能します。
例えば。すでにfoo
インスタンスをbar
イニシャライザに渡しているので、そこから取得します。
class bar(threading.Thread):
def __init__(self,fooInstance):
threading.Thread.__init__(self,name="bar")
self.var1 = fooInstance.var1
しかし、これはスレッドセーフですか?
ええ、そうですが、実際にバックグラウンドスレッドを開始したことがないからです。ただし、実際のコードでは、2つのスレッドが同時に実行され、両方がそのvar1
値にアクセスすると想定しています。その場合、何らかの同期がないとスレッドセーフではありません。例えば:
class foo(threading.Thread):
def __init__(self):
threading.Thread.__init__(self,name="foo=>bar")
self.var1 = {}
self.var1lock = threading.Lock()
class bar(threading.Thread):
def __init__(self,fooInstance):
threading.Thread.__init__(self,name="bar")
self.var1 = fooInstance.var1
self.var1lock = fooInstance.var1lock
そして今、これの代わりに:
self.var1[name] = value
… これをして:
with self.var1lock:
self.var1[name] = value
そして同様に、これの代わりに:
val = myOtherfunction(fooInstance.var1[arg]) //other function
… これをして:
with self.var1lock:
var1arg = var1[arg]
val = myOtherfunction(var1arg)
または…結局のところ、CPythonでは、dict内の単一のキーの値の更新(dict
サブクラスやカスタムマッピングクラスではなく、組み込みのみ!)は常にアトミックであり、おそらく常にアトミックになります。あなたがその事実に頼りたいのなら、あなたはそうすることができます。しかし、ロックが重大なパフォーマンスの問題であることが判明した場合にのみ、それを行います。そして、それを明確にするために、それを使用するたびにコメントしたいと思います。
値を共有するのではなく渡す方がよい場合、通常の答えはまたはその親戚の1つです。queue.Queue
ただし、これにはプログラムの再設計が必要です。たとえば、新しい/変更された各キーと値のペアをキューに渡したい場合があります。それは次のようになります:
class foo(threading.Thread):
def __init__(self):
threading.Thread.__init__(self,name="foo=>bar")
self.var1 = {}
self.q = queue.Queue()
def run(self):
b = bar(self)
b.start()
while True:
value, name = getvalue() // name is an string
self.var1[name] = value
self.q.put((name, value))
class bar(threading.Thread):
def __init__(self,fooInstance):
threading.Thread.__init__(self,name="bar")
self.var1 = copy.deepcopy(fooInstance.var1)
self.q = fooInstance.q
def _checkq(self):
while True:
try:
key, val = self.q.get_nowait()
except queue.Empty:
break
else:
self.var1[key] = val
def run(self):
while True:
self._checkq()
arg = myfunction() // somefunction (not shown for simplicity)
val = myOtherfunction(fooInstance.var1[arg]) //other function
print(val)
この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。
侵害の場合は、連絡してください[email protected]
コメントを追加