pthread_mutex_lock, wie nicht gesperrt wird, wenn es sich um denselben Thread handelt

8

Ich verwende pthread_mutex_t zum Sperren.

%Vor%

Sagen wir, ich habe nur einen Thread, der die Funktion aufruft, also: get1 sperrt den m_lock und ruft get2 auf, aber wenn er versucht, m_lock zu sperren, wartet er, dass die Sperre entsperrt wird (etwas, was nicht passiert) und wir haben einen Deadlock bekommen.

Meine Frage ist, wie kann ich diesen Fall vermeiden, wenn der gleiche Thread, der die Sperre in get1 gesperrt hat, nicht auf die Sperre in get2 warten muss (weil es der gleiche Thread ist)?

In Java zum Beispiel kann dieser Fall niemals auftreten, wenn Sie synchornized verwenden.

%Vor%

Kein Deadlock hier.

Ich möchte das gleiche Ergebnis in meinem C-Code bitte.

Danke.

    
Yaron Israeli 07.10.2016, 11:57
quelle

4 Antworten

11

Wie Kami Kaze in den Kommentaren angemerkt hat, ist dies kein Problem, da es nur einen Pfad gibt, der zu get2 führt. Dieser Pfad erwirbt bereits den Mutex. einfach weglassen es ein zweites Mal zu erwerben.

Im Allgemeinen ist es jedoch möglich, an Szenarien zu denken, bei denen es nicht so klar ist. In diesem Fall können Sie den Mutex rekursiv / reentrant machen:

  

In der Informatik ist der reentrante Mutex (rekursive Mutex, rekursive Sperre) eine bestimmte Art von gegenseitigem Ausschluss (Mutex) -Gerät, die mehrfach durch denselben Prozess / Thread gesperrt werden kann, ohne einen Deadlock zu verursachen.

In Ihren Einstellungen wäre dies über pthread_mutexattr_settype :

%Vor%     
Ami Tavory 07.10.2016, 12:03
quelle
0

Damit:

%Vor%

Sie haben die gesamte get2() gesperrt. Es macht also keinen Sinn, die selbe Sperre wieder in get2() function zu setzen. Entfernen Sie einfach den Code zum Sperren und Entsperren von get2() .

Wenn nur der Codeteil in get2() eine Sperre benötigt, dann entferne das Sperren und Entsperren von get1() function.

  

In Java zum Beispiel kann dieser Fall niemals vorkommen, wenn Sie ihn verwenden   synchronisiert.

In Ihrem Code sind die synchronisierten Regionen nicht miteinander verknüpft. Für einen ähnlichen Vergleich müssen Sie einen anderen Mutex in get2() Funktion verwenden.

    
usr 07.10.2016 12:03
quelle
0

Dies wird als Sperrrekursion bezeichnet.

Das letzte Argument von pthread_mutex_init ist eine attributes-Struktur. Sie können die Attribute so einstellen, dass rekursives Sperren mit pthread_mutexattr_settype(..., PTHREAD_MUTEX_RECURSIVE) möglich ist.

Aber ich muss hier redaktionelle Inhalte hinzufügen. Ich glaube sehr stark, dass die Sperrrekursion fast immer ein Bug ist. Oder es wird unmöglich sein, Fehler später in der Programmlebensdauer zu debuggen.

Eine Sperroperation kann so ausgelegt werden, dass "wenn die Sperrfunktion zurückkehrt, das durch die Sperre geschützte Objekt sich in einem bekannten Zustand befindet und dieser Zustand sich nicht ändert, bis die Entsperrfunktion aufgerufen wird". Das heißt, wenn get1 begonnen hat, das Objekt zu ändern, das Sie mit der Sperre schützen, und dann get2 diese Sperre rekuziert, wird dieser Vertrag zweimal unterbrochen. Erstens, weil get2 erfolgreich ist, die Sperre zu erhalten, während das Objekt nicht in einem bekannten Zustand ist, zweitens, weil das Objekt geändert wird, während get1 denkt, dass es die Sperre besitzt.

Sicher, wir kommen oft damit davon, Dinge wie diese zu tun, aber es ist eine schreckliche Übung. Überarbeiten Sie Ihr Programm, um Sperren nicht erneut zu berechnen. Der übliche Weg wäre eine Funktion namens get2_locked und get2 zu implementieren, die die Sperre aufruft und get2_locked aufruft, während get1 bereits weiß, dass sie die Sperre hat und get2_locked aufrufen würde.

    
Art 07.10.2016 12:11
quelle
0

Ich nehme an, dass get1 wirklich mehr tut, als nur die Sperre zu erhalten und get2 aufzurufen? Sonst was ist der Punkt von get1 ?

Wenn das der Fall ist, könntest du es lösen, indem du eine get3 -Funktion hast, die den Hauptteil von get2 (den Teil, den du hier nicht zeigst) macht und der nicht sperrt. Dann rufe diese neue Funktion stattdessen von get1 (und natürlich von get ) auf:

%Vor%     
Some programmer dude 07.10.2016 12:15
quelle

Tags und Links