2009-11-30 4 views
11

Das Threading-Modul in Python bietet zwei Arten von Sperren: Eine gemeinsame Sperre und eine Reentrant-Sperre. Es scheint mir, wenn ich ein Schloss brauche, sollte ich immer den RLock über das Lock ziehen; hauptsächlich um Deadlock-Situationen zu vermeiden.Ist RLock ein vernünftiger Standard gegenüber Lock?

Außerdem sehe ich zwei Punkte, wenn eine Sperre über einen RLOCK bevorzugen:

  • RLOCK eine kompliziertere innere Struktur hat und somit eine schlechtere Leistung haben kann.
  • Aus irgendeinem Grund möchte ich verhindern, dass ein Thread durch die Sperre rekursiv wird.

Ist meine Argumentation richtig? Kannst du auf andere Aspekte hinweisen?

+1

# 2 ist wahrscheinlich kein guter Grund; Der einzige Fall, bei dem es sich nicht um einen garantierten Deadlock handelt, ist, wenn die Rekursion nicht blockierend wird und eine vernünftige Vorgehensweise hat, wenn sie nicht verifizieren kann, dass sie die Sperre hält. Und # 1 gilt nicht für Python 3.2+. Ein legitimer Grund, "Lock" vorzuziehen, ist, wenn die Sperre in einem anderen Thread als dem, der sie erworben hat, freigegeben werden muss. – ShadowRanger

Antwort

10

Zwei Punkte:

  • In offiziell freigegebenen Python-Versionen (2.4, 2.5 ... bis zu 3,1), ist ein RLOCK viel langsamer als ein Lock, weil Schlösser in C und RLocks in Python implementiert werden (dies wird in 3.2)
  • Eine Sperre kann von jedem Thread freigegeben ändern (nicht unbedingt den Faden, die (zu erwerben) d es), während ein RLOCK vom selben Thread freigegeben werden muss, die sie erworben

Unterm Strich würde ich vorschlagen, nur einen RLock zu verwenden, wenn er der Semantik entspricht, die Sie sind Suchen Sie nach, ansonsten bleiben Sie standardmäßig bei Locks.

+1

Das heißt, 'RLock' kann Code vereinfachen. Wenn es zwei Methoden gibt, die beide die Sperre halten müssen und eine die andere aufruft, müssen Sie die "innere" Methode in ein nicht gesperrtes Dienstprogramm aufteilen, wobei der öffentliche Name gesperrt und die innere Methode aufgerufen wird. während die "äußere" Methode das entsperrte Dienstprogramm direkt aufruft. Und Sie müssen dies jedes Mal tun, wenn Sie Codewiederverwendung dieses Formulars durchführen. Darüber hinaus wird mit 'RLock' das Risiko beseitigt, dass ein Thread in einem Thread stillgelegt und in einem anderen entsperrt wird (es erzwingt das Sperren und Entsperren desselben Threads). verhindert Fehler im allgemeinen Fall. – ShadowRanger

+0

Angesichts der Leistungseinbußen in 3.1 und unten, konnte ich "Lock" aus praktischen Gründen allgemein empfehlen, aber in 3.2+ ist "RLock" weniger kompliziert zu verwenden, verhindert häufige Fehler und ist ebenso effizient; Sie verwenden 'Lock' nur dann, wenn Sie' Lock'-spezifische Funktionen benötigen (zB Cross-Thread-Erfassung/Freigabe, Verwendung als Barriere für Kellner; Kellner erstellt 'Lock',' akquirieren's einmal, ergänzt eine Liste von Warten Sie Locks, 'akquirieren' Sie wieder, blockieren Sie, alerter, dann '' s 's loslassen, um den 'Kellner' weiterzumachen (natürlich beschreibe ich nur, was' Condition' für Sie tut, also tu das nicht selbst) . – ShadowRanger

3

Normalerweise sollten Sie Ihren Code so strukturieren, dass Sie im normalen Betrieb niemals rekursiv sperren müssen (im Grunde zwingt er Sie, Sperren um die geschützten Datenstrukturen herum zu verwenden, die sie schützen). Daher möchten Sie eine anomale rekursive Sperre abfangen.

+0

Ihre Antwort impliziert, dass [das Beispiel] (http://effbot.org/zone/thread-synchronization.htm#re-entrant-locks-rlock), das verwendet wird, um "RLock" zu motivieren, in erster Linie neu geschrieben werden sollte tigere Schlösser, an denen es nicht "RLock" brauchen. Würdest du zustimmen? Und wenn ja, was ist ein gutes Beispiel, das die Notwendigkeit von "RLock" motiviert? – max

Verwandte Themen