2012-06-19 4 views
5

私は異なるスレッドを持っており、処理後に共通のリストにデータを入れます。リストのためにPythonで構築されたものや、単一のスレッドだけがアクセスできる配列がありますか?第二に、それを行うのエレガントな方法は何ですか?Pythonのリストを同期するには?

答えて

1

標準ライブラリはどうですか。Queue

4

threadingは、クリティカルセクション全体を保護する必要がある場合、またはQueueモジュールがスレッドセーフであるキューを提供する場合は、オブジェクトを提供します。

4

Thread synchronisation mechanisms in Pythonによれば、リストから1つのアイテムを読み取り、その場所のリストを変更することは原子的であることが保証されています。これが正しければ(それは部分的にキューモジュールの存在そのものと矛盾しているようだが)、その後、あなたのコードは、フォームのすべての場合:

try: 
    val = mylist.pop() 
except IndexError: 
    # wait for a while or exit 
else: 
    # process val 

そしてmylistに入れてすべてが.append()によって行われ、その後、あなたのコードはすでにスレッドセーフです。そのスコアで1つのドキュメントを信頼しない場合は、queue.queueを使用します。これはすべての同期を行い、並行プログラムの場合はlistより優れたAPIを備えています。特に、無期限にブロックするか、タイムアウトするかを選択できます、あなたは他のスレッドが平均時間で乗っている可能性がある場合は、.pop()が動作するのを待っています。 numpyの配列の場合

、とあなたはプロデューサ/コンシューマキューよりも多くを必要とする一般的にはどのような場合でも、threadingからLockまたはRLockを使用する - これらは、コンテキストマネージャプロトコルを実装するので、それらを使用することは非常に簡単です:

with mylock: 
    # Process as necessarry 

そして、pythonはwithブロックの終了時にロックが解放されたことを保証します。例外を発生させるような場合など、トリッキーなケースを含みます。

最後に、threadingよりもアプリケーションに適しているかどうかを検討してください。Pythonのスレッドは実際には同時に実行されることは保証されていません。また、CPythonではCレベルのコードにドロップできます。 multiprocessingはその問題を回避しますが、余分なオーバーヘッドが発生する可能性があります。まだお持ちでない場合は、ドキュメントを読んでニーズに適したものを判断する必要があります。

+0

は 'mylist.pop(0)' atmoicですか? – willsteel

+0

'with mylock:'リマインダーをありがとう。 Imho RLocksは、オブジェクト指向プログラミングのクリティカルセクションを保護するために、この方法を使用することがよくあります。 – jjmontes

+0

@willsteelの回答が確定しているので、リストがどのように実装されているのかPythonのソースコードを見てみることをお勧めしますが、 'mylist.pop()'が(これも私は明確に答えることができません。そのため、他の同期メソッドについても言及していますが、これはPythonの実装全体でも変更される可能性があります)。特に、CPython *のすべてのCレベルのコードは、GILによって保護されるかもしれません(しかし、それをリリースするオプションがあります)。 'pop'(たぶん)は引数にかかわらずGILを解放するかどうかを指定します。 – lvc

関連する問題