Python組み込みコンテナ(リスト、ベクター、セット...)がスレッドセーフであるかどうかを知りたいですか?または、共有のロック/ロック解除環境を実装する必要がありますか?変数?
Pythonで変更されるすべての共有変数に独自のロックを実装する必要があります。変更されない変数からの読み取りについて心配する必要はありません(つまり、同時読み取りは可能です)。そのため、不変の型(frozenset
、Tuple
、str
)はおそらく安全ですが、害はありません。変更するもの-list
、set
、dict
、およびその他のほとんどのオブジェクトでは、独自のロックメカニズムを使用する必要があります(インプレース操作はこれらのほとんどで、スレッドは非常に厄介なバグにつながる可能性があります-ロックを実装することもできますが、それは非常に簡単です)。
ちなみに、あなたがこれを知っているかどうかはわかりませんが、Python-threading.lockオブジェクトを作成すると、ロックが非常に簡単になり、次のように取得/解放できます。
import threading
list1Lock = threading.Lock()
with list1Lock:
# change or read from the list here
# continue doing other stuff (the lock is released when you leave the with block)
Python 2.5では、from __future__ import with_statement
; Python 2.4以前はこれがないため、acquire()/ release()呼び出しをtry:...finally:
ブロック:
import threading
list1Lock = threading.Lock()
try:
list1Lock.acquire()
# change or read from the list here
finally:
list1Lock.release()
# continue doing other stuff (the lock is released when you leave the with block)
はい、もちろんあなたはもちろん注意する必要があります
例えば:
2つのスレッドが1つのアイテムのみのリストからpop()
にレースしている場合、1つのスレッドはアイテムを正常に取得し、もう1つのスレッドはIndexError
を取得します
このようなコードはスレッドセーフではありません
if L:
item=L.pop() # L might be empty by the time this line gets executed
このように書いてください
try:
item=L.pop()
except IndexError:
# No items left
スレッドのCコードでGILを無効にしない限り、スレッドセーフです。
キューモジュールは、マルチプロデューサー、マルチコンシューマーキューを実装します。これは、複数のスレッド間で情報を安全に交換する必要があるスレッドプログラミングで特に役立ちます。このモジュールのQueueクラスは、必要なすべてのロックセマンティクスを実装します。