5

私は次のコードを持っています:

def query(self,query):
  lock = QMutexLocker(self.mutex)
  reply = self.conn.query(query)
  if (re.search("error", reply) != None):
    raise GeneralError("Query error")

  #more code...  
  return reply

ここで、例外がスローされた場合、ロックが削除されていないように見える場合は、ミューテックスが解放されない原因になります。もちろん、どこでも「デルロック」を行うことができますが、それはqmutexlockerのすべてのポイントを奪います。これはPythonのガベージコレクションと関係がありますか?もしそうなら、それはQMutexLockerがPythonでまったく使用できないことを意味する必要がありますか?

4

2 に答える 2

12

QMutexLockerを正しく使用していません。コンテキストマネージャーのように使用します。

from PyQt4.QtCore import QMutex, QMutexLocker

def bad_lock(aLock):
    locker = QMutexLocker(aLock)
    print "Locked"
    raise RuntimeError("Test exception")

    return "Should not get here"

def good_lock(aLock):
    with QMutexLocker(aLock):
        print "Locked"
        raise RuntimeError("Test exception")

    return "Should not get here"

lock = QMutex()

bad_lock(lock)
print lock.tryLock()
# False

lock.unlock()

good_lock(lock)
print lock.tryLock()
# True

テストでは、最初の例で、ロックがロックされたままになっていることがわかります。2番目の例では、例外が発生すると、コンテキストマネージャーは関数を終了する前にロックを解放します。

C ++で使用すると、QMutexLockerが想定どおりに動作し、スコープが終了するたびにロックが解除されると確信しています。しかし、Pythonでは、ご存知のように、ロック解除を行うためにガベージコレクターに依存するべきではありません。ステートメントを介したコンテキストマネージャーはwith、これに最適です。ちなみに、このクラスのC ++の例では、関数の先頭で作成されているだけであることがわかります。一方、Pythonバージョンには__enter____exit__メソッドの両方があります。

最後に、withコンテキストを使用すると、重要なコードブロックをロックでラップして、ロックを設定する必要がある量を制限できるため、次のように実行できます。

def good_lock(aLock):

    # do a bunch of stuff here
    ...

    # critical section
    with QMutexLocker(aLock):
        # do critical stuff here
        ...

    # do other stuff here
    ...

    return True
于 2012-06-30T03:35:28.190 に答える
0

例外を発生させる前にミューテックスを解放したい場合は、それを解放します。

def query(self, query):
    lock = QMutexLocker(self.mutex)
    reply = self.conn.query(query)
    if re.search("error", reply):
        lock.unlock()
        raise GeneralError("Query error")

範囲外になったときlockにすぐにリリースされることを期待している場合は、インタプリタが多すぎることを期待しています。ロックを解除するタイミングと理由が正確にわかっているので、それを実行します。

原則として、Pythonまたはその他の場所では、ミューテックスを可能な限り最小のアクションにバインドする必要があります。クエリが実行しているものはすべて実際には保護が必要であり、への呼び出し後も保護が必要であることをご存知だと思いますself.conn.query

コメントに応じて追加

それは、私が見逃した「QMutexLockerがまったく使用できないことを意味しているに違いない」という公正な点です。私はあなたがPySide.QtCore.QMutexLockerを参照していると仮定します。

これで、PySide.QtCore.QMutexLockerオブジェクトが破棄されたとき(ロッカーは自動変数であるため関数が戻ったとき)、ミューテックスは常にロック解除されます。

autoPythonには変数ストレージクラスのようなものがないので、それはありそうにありません。さらに調査すると、これは「C ++ライブラリをラップして、スコープのセマンティクスが機能すると仮定する」ことが証明されると思います。この推測が正しければ、withステートメントを使用して、信頼性の高いロック解除をより確実に行うことができます。

于 2012-06-29T12:48:15.647 に答える