2013-08-23 11 views
8

多くのスレッドとプロセスを使用している間にファイルが決して壊れないようにする正しい解決策は何ですか?スレッドとプロセスを使用して同じファイルに同時に書き込む

オープンエラーを気にするスレッド用のバージョン。私はmultiprocessing.Lock

を使用しますが、私は2つの工程と、第1のプロセス自身の2つのスレッド(各1つの使用ファイル)

をしたい場合は、単に理論が存在しなければならないと思うのプロセスの

lock = threading.RLock() 
with lock: 
    try: 
    f = open(file, 'a') 
    try: 
     f.write('sth') 
    finally: 
     f.close() # try close in any circumstances if open passed 
    except: 
    pass # when open failed 

が、スレッドとプロセスとの同期をどのように組み合わせるかを知りたい スレッドはプロセスからそれを "継承"するため、プロセス間の同期のみが必要ですか?

および2.「私は書き込みが失敗したときに上記のコードの場合には、ネストされた試しが必要な場合はわからない、と私たちはこのISNながら開かれたファイル(それはロック解除後に開かれたままになります場合はどのような)

+0

補足として、 'try' /' finally'は 'with'ステートメントで置き換えることができます。また、 'except:pass'は通常は悪い考えです。特定の例外を呑み込もうとしているのであれば、それだけではなく、すべてを絞ってください。ここを見てみると、intをファイル名として渡すような愚かなエラーがあった人から何十件もの質問を見つけることができます。 – abarnert

+0

また、特にファイルをロックする場合は、汎用スレッド/プロセスロックの代わりに、POSIXでのアドバイザリファイルロックとWindowsでの排他的ファイルアクセスの使用を検討することをお勧めします。 – abarnert

+1

もう1つの可能性は、単一のスレッドから追加するすべてのファイルを(1つのプロセスで)実行し、他の人にメッセージをキューに投稿させることです(組み込みのため、同期は必要ありません)。 – abarnert

答えて

7

を閉じたいですthe docsから完全にはっきりしているので、マルチプロセッシング同期プリミティブは、実際にはスレッドも同期させます。あなたはこのコードを実行した場合たとえば

、:

import multiprocessing 
import sys 
import threading 
import time 

lock = multiprocessing.Lock() 

def f(i): 
    with lock: 
     for _ in range(10): 
      sys.stderr.write(i) 
      time.sleep(1) 

t1 = threading.Thread(target=f, args=['1']) 
t2 = threading.Thread(target=f, args=['2']) 
t1.start() 
t2.start() 
t1.join() 
t2.join() 

...出力は常に1111111111222222222または22222222221111111111、両者の混合物ではないだろう。

ロックは、WindowsではWin32カーネル同期オブジェクト、POSIXプラットフォームではセマフォをサポートし、他のプラットフォームでは実装されていません。 (あなたは、ドキュメントで説明したように、他のプラットフォームでImportErrorを上げるであろう、import multiprocessing.semaphoreでこれをテストすることができます。)


を言われて、それは限り、ロックの二つのレベルを持つことは確か安全だという常に正しい順序で使用します。つまり、プロセスにmultiprocessing.Lockがあることを保証できない限り、threading.Lockを絶対に取得しないでください。

これを賢く行うと、パフォーマンスが向上します。 (Windowsおよび一部のPOSIXプラットフォームでのクロスプロセスロックは、プロセス内ロックよりも数桁遅い可能性があります)。明らかにパフォーマンスには役立ちませんし、実際には少し遅くなりますが(測定するには十分ではないかもしれませんが)、直接的なメリットはありません。もちろん、読者は、スレッド間でロックが動作することがわからなくてもコードが正しいことを知っていることがあります。また、場合によってはプロセス間デッドロックをデバッグするよりもintraprocessデッドロックをデバッグする方が簡単かもしれませんが、ほとんどの場合、これらは余分な複雑さの十分な理由です。

関連する問題