Heim > häufiges Problem > Wie vermeide ich einen Deadlock?

Wie vermeide ich einen Deadlock?

coldplay.xixi
Freigeben: 2020-06-24 14:33:24
Original
4541 Leute haben es durchsucht

Wie vermeide ich einen Deadlock?

Methoden zur Vermeidung von Deadlocks:

Ein Deadlock tritt auf, wenn zwei Threads darauf warten, dass der andere Threads Ressourcen freigibt. Der Python-Interpreter führt keine Überwachung durch und ergreift keine aktiven Maßnahmen, um mit Deadlock-Situationen umzugehen. Daher sollten Maßnahmen ergriffen werden, um Deadlocks bei der Multithread-Programmierung zu vermeiden.

Sobald ein Deadlock auftritt, tritt im gesamten Programm keine Ausnahme auf und es wird auch keine Eingabeaufforderung ausgegeben. Alle Threads werden jedoch blockiert und können nicht fortgesetzt werden.

Ein Deadlock kann sehr leicht auftreten, insbesondere wenn mehrere Synchronisierungsmonitore im System vorhanden sind. Das folgende Programm verursacht einen Deadlock:

import threading
import time
class A:
    def __init__(self):
        self.lock = threading.RLock()
    def foo(self, b):
        try:
            self.lock.acquire()
            print("当前线程名: " + threading.current_thread().name\
                + " 进入了A实例的foo()方法" )     # ①
            time.sleep(0.2)
            print("当前线程名: " + threading.current_thread().name\
                + " 企图调用B实例的last()方法")   # ③
            b.last()
        finally:
            self.lock.release()
    def last(self):
        try:
            self.lock.acquire()
            print("进入了A类的last()方法内部")
        finally:
            self.lock.release()
class B:
    def __init__(self):
        self.lock = threading.RLock()
    def bar(self, a):
        try:
            self.lock.acquire()
            print("当前线程名: " + threading.current_thread().name\
                + " 进入了B实例的bar()方法" )   # ②
            time.sleep(0.2)
            print("当前线程名: " + threading.current_thread().name\
                + " 企图调用A实例的last()方法")  # ④
            a.last()
        finally:
            self.lock.release()
    def last(self):
        try:
            self.lock.acquire()
            print("进入了B类的last()方法内部")
        finally:
            self.lock.release()
a = A()
b = B()
def init():
    threading.current_thread().name = "主线程"
    # 调用a对象的foo()方法
    a.foo(b)
    print("进入了主线程之后")
def action():
    threading.current_thread().name = "副线程"
    # 调用b对象的bar()方法
    b.bar(a)
    print("进入了副线程之后")
# 以action为target启动新线程
threading.Thread(target=action).start()
# 调用init()函数
init()
Nach dem Login kopieren

Führen Sie das obige Programm aus und es wird den gezeigten Effekt sehen in Abbildung 1.

Wie vermeide ich einen Deadlock?

Abbildung 1 Deadlock-Effekt

Wie aus Abbildung 1 ersichtlich ist, kann das Programm weder nach unten ausführen noch eine Abnormalität auslösen "Patt". Der Grund dafür ist, dass die Methoden von Objekt A und Objekt B im obigen Programm beide Thread-sichere Methoden sind.

Im Programm werden zwei Threads ausgeführt. Der Thread-Ausführungskörper des sekundären Threads ist die Funktion action() und der Thread-Ausführungskörper des Hauptthreads ist die Funktion init() (die Hauptprogrammaufrufe). die init()-Funktion). Lassen Sie in der Funktion action() das B-Objekt die Methode bar() aufrufen und in der Funktion init() das A-Objekt die Methode foo() aufrufen.

Abbildung 1 zeigt, dass die Funktion action() zuerst ausgeführt wird und die bar()-Methode des B-Objekts aufruft. Bevor die bar()-Methode aufgerufen wird, sperrt der Thread die Sperre des B-Objekts (wenn die Das Programm wird in ②-Code ausgeführt, der sekundäre Thread pausiert für 0,2 Sekunden. Die CPU wechselt zur Ausführung eines anderen Threads und lässt das A-Objekt die foo()-Methode ausführen, sodass Sie sehen, dass der Hauptthread mit der Ausführung der foo()-Methode beginnt der A-Instanz: Dieser Thread sperrt die Sperre von Objekt A (wenn das Programm Code ① ausführt, pausiert der Hauptthread ebenfalls für 0,2 Sekunden).

Als nächstes wacht der sekundäre Thread zuerst auf und wird weiter nach unten ausgeführt, bis er Code ④ erreicht und hofft, die last()-Methode des A-Objekts aufzurufen (bevor diese Methode ausgeführt wird, wird die Sperre des A-Objekts aktiviert). muss die erste Sperre sein), aber zu diesem Zeitpunkt behält der Hauptthread die Sperre des A-Objekts bei, sodass der sekundäre Thread blockiert ist.

Als nächstes sollte der Hauptthread aufwachen und mit der Ausführung fortfahren, bis er Code ③ erreicht, in dem er hofft, die last()-Methode des B-Objekts aufzurufen (bevor diese Methode ausgeführt wird, muss das B-Objekt zunächst gesperrt sein). , aber zu diesem Zeitpunkt gibt der sekundäre Thread die Sperre des B-Objekts nicht frei.

Zu diesem Zeitpunkt hält der Hauptthread die Sperre für Objekt A und wartet darauf, dass Objekt B gesperrt wird, während der sekundäre Thread die Sperre für Objekt B hält und darauf wartet, dass Objekt A gesperrt wird Warten Sie aufeinander. Die Sperre wird zuerst aufgehoben, sodass ein Deadlock auftritt.

Deadlocks sollten in Programmen nicht auftreten. Deadlocks sollten beim Schreiben von Programmen so weit wie möglich vermieden werden. Es gibt mehrere gängige Möglichkeiten, Deadlock-Probleme zu lösen:

  1. Vermeiden Sie mehrere Sperren. Versuchen Sie zu vermeiden, mehrere Sperren für denselben Thread zu sperren. Im obigen Deadlock-Programm muss beispielsweise der Hauptthread die Sperre von zwei Objekten A und B sperren, und der sekundäre Thread muss auch die Sperre von zwei Objekten A und B sperren, was die versteckte Gefahr eines Deadlocks birgt.

  2. hat die gleiche Sperrreihenfolge. Wenn mehrere Threads mehrere Sperren sperren müssen, sollten sie sicherstellen, dass sie Sperren in derselben Reihenfolge anfordern. Im obigen Deadlock-Programm sperrt beispielsweise der Hauptthread zuerst die Sperre von Objekt A und dann die Sperre von Objekt B, während der sekundäre Thread zuerst die Sperre von Objekt B und dann die Sperre von Objekt A sperrt. Diese Sperrsequenz kann leicht verschachtelte Sperren bilden, was zu Deadlocks führen kann. Dieses Problem kann vermieden werden, wenn der Hauptthread und der sekundäre Thread in derselben Reihenfolge gesperrt werden.

  3. Zeitsperre verwenden. Das Programm kann den Timeout-Parameter angeben, wenn die Methode „acquire()“ zum Sperren aufgerufen wird. Dieser Parameter gibt an, dass die Sperre nach Timeout-Sekunden automatisch aufgehoben wird, sodass der Deadlock aufgehoben werden kann.

  4. Deadlock-Erkennung. Die Deadlock-Erkennung ist ein Mechanismus zur Verhinderung von Deadlocks, der auf algorithmischen Mechanismen beruht. Sie zielt hauptsächlich auf Szenarien ab, in denen eine sequentielle Sperrung nicht möglich ist und keine zeitgesteuerten Sperren verwendet werden können.

Das obige ist der detaillierte Inhalt vonWie vermeide ich einen Deadlock?. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Verwandte Etiketten:
Quelle:php.cn
Erklärung dieser Website
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn
Beliebte Tutorials
Mehr>
Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage