2011-01-07 2 views
13

Pythonのロック注釈は、Javaメソッドとの "同期"キーワードと同じ効果をPythonメソッドにも与えていますか?pythonロックメソッドの注釈

+0

コメントありがとうございます。 – paweloque

+3

それはあなたが何をしているかによって異なります。 Pythonは「グローバルインタプリタロック」を持っているため、一度に1つのスレッドしかPythonコードを実行することができず、複数のコアを利用することはできません。しかし、あなたのコードがディスクへのアクセスやネットワークからのデータを待っている場合や、numpyの計算を待っている場合は、マルチスレッドが機能します。 –

+0

ザビエル、ナンセンスを吐き出さないでください。マルチスレッド化は必ずしも悪い考えではありません。それはいくつかのCPUバウンドコードのためにマルチコアシステム上でそのGILのprobsを持っていることを認め...しかし、それは全体のことを "悪い考え"と呼ぶには不十分です。 –

答えて

15

私は組み込みの機能がPythonで存在しないと仮定することができますが、あなたはそれがthisリンクからJavaでどのように機能するかを理解し、それを実装することができます作成​​

すべてのJavaオブジェクト、すべてのクラスがロードされ を含め、関連するがあります ロックまたはモニタ。 同期ブロック内のコードを置くことは、コンパイラ 追記命令は、コードを実行する 前に指定されたオブジェクトの ロックを取得し、その後それ を解放することができる(いずれかのコードため 終了正常または異常)。 ロックを取得してから を解放するまでの間に、スレッドは がロックを所有していると言います。スレッド ロックを取得したい場合、 スレッドBがすでにそれを所有している場合は、 スレッドAはスレッドBが にリリースされるのを待たなければなりません。ので、多分このような何かが動作することができます

:Javaで

synchronized文:

public class Java { 
    static private int count = 0; 

    public void increment() { 
     synchronized (this) { 
      count++; 
     } 
    } 
} 

になった:

import threading 

class Java: 
    cout = 0 
    lock = threading.RLock() 

    def increment(): 
     with Java.lock: 
      Java.cout += 1 

とJavaでの同期方法:

public class Java { 
    static private int count = 0; 

    public synchronized void increment() { 
     count ++; 
    } 
} 

になった:

import threading 

def synchronized(method): 
    """ Work with instance method only !!! """ 

    def new_method(self, *arg, **kws): 
     with self.lock: 
      return method(self, *arg, **kws) 


    return new_method 

class Java: 
    count = 0 
    lock = threading.RLock() 

    @synchronized 
    def incremenet(self): 
     Java.count += 1 

明示的、暗黙よりも優れています。

N.B:私のJava知識は非常に限定されています。このJava機能についての私の講義は、多分私が何かを見逃しているかもしれません。

NB:私が作成したロックはクラス変数なので、クラスレベルで同期が行われるようにします。インスタンスレベルで同期を行いたい場合は、Javaのやり方を考えてください。変化する。

+3

また、取得メソッドと解放メソッドの代わりに 'with lock:'を使用することもできます。 –

+0

@Thomas K:コメントありがとうございました:) – mouad

+1

あなたのデコレータに 'return'を追加したいと思うかもしれません:あなたの例では必要ではありませんが、何かを返すメソッドでデコレータを再利用することができます。また、インスタンスを介してクラス変数にアクセスできるように、クラスに割り当てられていない限り、クラスを介して明示的にロックにアクセスする特別な理由はありません。 – Duncan

1

は、私は時々、このようデコレータを使用します。しかし、最初に装飾されたメソッドを呼び出すときに

def synchronized(f): 
    @functools.wraps(f) 
    def wrapper(self, *args, **kwargs): 
     try: 
      _ = self._lock 
     except AttributeError: 
      self._lock = threading.Lock() 

     with self._lock: 
      return f(self, *args, **kwargs) 
    return wrapper 

このソリューションは、競合状態を持っています。この問題を避ける最も簡単な方法は、最初に他のスレッドが実行されていないときに同期メソッドを呼び出すことです。を手動で割り当てます。__init__