Am 14. September 2017 haben wir eine überarbeitete Fassung unserer Datenschutzrichtlinie veröffentlicht. Wenn Sie video2brain.com weiterhin nutzen, erklären Sie sich mit diesem überarbeiteten Dokument einverstanden. Bitte lesen Sie es deshalb sorgfältig durch.

C++: Multithreading

Deadlocks

LinkedIn Learning kostenlos und unverbindlich testen!

Jetzt testen Alle Abonnements anzeigen
Verwenden Threads Mutexe und geben diese nicht mehr frei, entsteht leicht ein Deadlock: Die Threads blockieren sich gegenseitig.
05:24

Transkript

In dieser Lektion möchte ich einen klassischen Begriff aus der Multithreading-Programmierung vorstellen. Klassisch und gleichzeitig legendär: "Deadlock". Ein Deadlock ist eine Verklemmung, indem zwei oder mehr Threads blockiert sind, da jeder Thread auf die Freigabe der Ressource des anderen Threads wartet, bevor er seine Ressource freigibt. Es gibt noch andere Namen dafür "deadly embrace", die "tödliche Umarmung" oder vor kurzem habe ich auch gehört "Kiss of death", finde ich auch schön. Sie sehen, hier wird es gefährlich. Was ist das Resultat von Deadlock? Das Programm ist für immer blockiert. Sie müssen es tatsächlich abbrechen, es geht nichts mehr. Ein Irrglauben möchte ich hier gleich beseitigen. Um ein Deadlock zu erzeugen, brauchen Sie keinen Mutex. Jede Ressource, die nicht angefordert wird und auf etwas wartet, besitzt Potential für ein Deadlock. Das kann zum Beispiel ein Anforderung von Speicher sein und es kann auch ein Zugriff auf eine Datei sein. Jetzt will ich Ihnen noch zwei Szenarien von Deadlocks vorstellen. Das erste Szenario ist ein klassiker, schauen Sie es sich genau an. Ich habe hier ein "mutex m", ich lock den, ich unlock den, da zwischen verwende ich eine shardVariable und diese shardVariable ruft unbekannten Code auf oder eine unbekannte Funktion "getVar". Welche Probleme gibt es hier? Erstes Problem. Wenn getVar eine Ausnahmen wirft, wird m.unlock () nicht aufgerufen, Deadlock. Zweites Problem, ich rufe, während ich das Lock besitze, eine unbekannte Funktion auf. Was passiert nun, wenn die Funktion "getVar" selbst nochmal die gleiche Funktion verwenden will, Deadlock. Das war ein Szenarium, es gibt aber noch ein anders typisches Szenario, locken in verschiedener Reihenfolge. Ich habe hier ein Thread 1 und ein Thread 2. Thread 1 benötigt ein Lock: Lock 1 und Lock 2 Thread 2 benötigt ein Lock: Lock 1 und Lock 2. Dummerweise locken Thread 1 und Thread 2 ihren Mutex in verschiedene Reihenfolge. Das heißt, Thread 1 zieht erst den Lock1 dann Lock 2. Thread 2 zieht erst den Lock 2 und dann den Lock 1. Und wenn die jetzt ungeschickt verschränkt ausgeführt werden, haben Sie natürlich auch wieder das Gleiche, Sie haben Deadlock. Was ist die Lösung? Die Lösung ist oft eine "lock_guard" oder eine "unique_lock", das heißt, Sie verpacken ein Mutex in ein sogenannte "lock_guard" und "unique_lock". Da der "lock_guard" automatisch, genauso wie die "unique_lock" sein Mutex wieder freigibt. Das heißt, in diesem Fall, er ruft "implizit m.unlock ()" auf. Das war die Theorie, jetzt möchte ich Ihnen noch ein Deadlock in der praxis zeigen. So, hier ist das Programm mit dem ich ziemlich einfach ein Deadlock konstruieren konnte. Zuerst, gibt es hier CriticalData, CriticalData repräsentiert das Datum, dass ich schützen will, darum hat das intern auch ein Mutex. Das CriticalData benötige ich in der Funktion Deadlock. Die Funktion heißt nicht um sonst so. Deadlock bekommt zwei CriticalData A und B und was macht es? Es zieht den ersten Lock "a.mut.lock", schläft nur eine Millisekunde, zieht den zweiten Lock "b.mut.lock", tut irgendwas wichtiges und dann gibt es die Mutexe wieder frei, indem es unlock aufruft. Und das sind die zwei Threads. Thread 1 erhält per Reference C1 und C2. Thread 2 erhält per Reference C2 und C1. Das Entscheidende hier ist, dass ich die Funktion Deadlock aufrufe, wie den CriticalData und eben aufrufe in verschiedener Reihenfolge. Hier erhalte ich C1, C2 und hier erhalte ich C2, C1 und schauen Sie mal was passiet. Es geht nichts mehr. Thread 1 führt "get the first Mutex" aus, dann schläft er nur eine Millisekunde und das recht aus, dass Thread 2 auf "std: :cout" schreibt, beziehungsweise den Mutex lockt und dann versucht, dass Thread 1 Mutex B zu locken, Mutex B kann aber nicht locken, weil die bereits das Thread 2 gelockt hat und jetzt haben wir diesen verschränkten Zugriff, der typisch ist für Deadlocks, die dann entstehen, wenn Mutexe in verschiedene Reihenfolge gelockt werden. In dieser Lektion habe ich Ihnen Deadlocks genauer vorgestellt und Ihnen zwei typische Varianten vorgestellt, wie Sie Deadlocks konstruieren können. Auch wenn ich es hier konstruiert habe, so tauchen sie tatsächlich sehr oft in Produktivcode auf. Eine Variante ist, dass Sie in Lock halten und währenddessen versuchen eine unbekannte Funktionalität aufzurufen, führt natürlich dazu, dass unter Umständen nochmal ein Lock aufgerufen wird. Zweite Variante ist, dass Sie Mutexe in verschiedene Reihenfolge aufrufen und die Mutexe eben Locks ziehen.

C++: Multithreading

Lernen Sie die High-Level Threading-Schnittstelle in C++ kennenb und nutzen, die Sie in Form von Threads, Tasks, Locks und Bedingungsvariablen zur Anwendung bringen.

2 Std. 40 min (39 Videos)
Derzeit sind keine Feedbacks vorhanden...
 
Software:
Exklusiv für Abo-Kunden
Erscheinungsdatum:16.08.2016

Dieser Online-Kurs ist als Download und als Streaming-Video verfügbar. Die gute Nachricht: Sie müssen sich nicht entscheiden - sobald Sie das Training erwerben, erhalten Sie Zugang zu beiden Optionen!

Der Download ermöglicht Ihnen die Offline-Nutzung des Trainings und bietet die Vorteile einer benutzerfreundlichen Abspielumgebung. Wenn Sie an verschiedenen Computern arbeiten, oder nicht den ganzen Kurs auf einmal herunterladen möchten, loggen Sie sich auf dieser Seite ein, um alle Videos des Trainings als Streaming-Video anzusehen.

Wir hoffen, dass Sie viel Freude und Erfolg mit diesem Video-Training haben werden. Falls Sie irgendwelche Fragen haben, zögern Sie nicht uns zu kontaktieren!