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

Datenübergabe an Threads

LinkedIn Learning kostenlos und unverbindlich testen!

Jetzt testen Alle Abonnements anzeigen
Daten können an Threads kopiert oder per Referenz übergeben werden. Ersteres sollte der Standard sein.
06:32

Transkript

In diesem Lektion möchte ich Ihnen vorstellen, welche Probleme es geben kann, wenn Sie Daten an Threads übergeben. Insbesondere will ich Ihnen zeigen, wie Sie Daten per Kopie oder auch per Referenz als Threads übergeben können. Okay. Daten sollen per Default in den Thread kopiert werden, das heißt, wenn Sie Daten in Thread übergeben und Sie kopieren die Daten in den Kinder-Thread, haben Sie immer die Garantie, dass die Daten solang gültig sind, solang der Kind-Thread läuft. Diese Garantie haben Sie aber nicht mehr, wenn Sie die Daten per Referenz an die Kinder-Threads übergeben. Schauen Sie sich mal das Beispiel hier an. Hier habe ich einen Standard String, im Wert "C++11" und hierbei gebe ich die Daten per Kopie, hier per Referenz da steht [unverständlich], durch das "ist gleich Zeichen" drücke ich aus, dass die Daten S vom umgebenden Scoup reinkopiert worden. Okay. Damit bin ich auf der sicheren Seite. Dann ruft der Erzeuger-Thread "t.join" auf, wartet also bis sein Kind fertig ist, das ist wohldefiniert. Hier habe ich einen Problem oder anders ausgedrückt es kann Probleme entstehen. Das zeige ich Ihnen gleich im Beispiel. Was ist das Problem? Der Thread T nimmt seine Daten per Referenz, dieses &-Symbol hier an und er arbeitet auf diese Daten, die dem Erzeuger-Thread gehören in diesem Fall ist S, weiter. Das heißt, wenn der Erzeuger-Thread kürzer lebt, wie sein Kind-Thread, dann arbeitet der Kind-Thread auf S, obwohl S eigentlich gar nicht mehr gültig ist. Okay, genau das habe ich hier erreicht, weil ich hier durch die "t.detach" zum Erzeuger-Thread gesagt habe, trenne dich von der Lebenszeit deines Kindes. Und genau das Beispiel, will ich Ihnen jetzt in Aktion zeigen. Zugegeben, das Programm ist ein bisschen konstruiert, aber Sie werden schnell sehen, welche Probleme entstehen können, wenn Ihr Kinder-Thread seine Daten per Referenz annimmt und sich dazu noch der Erzeuger-Thread von der Lebenszeit seines Kinder-Thread trennt. Erstmal das hier ist das Arbeitspaket, was jeder Kinder-Thread auszuführen hat. Ich habe nur einen. Was macht der Kinder-Thread? Schauen wir es uns mal von Hauptprogramm ausgehend an. Zuerst definiere ich hier in der Variable "valSleeper". Die initialisiere ich mit 1000, dann starte ich hier den Thread T, mit dem Funktionsobjekt, genauer mit der Instanz des Funktionsobjekts "Sleeper" übergibt dem Konstruktor "valSleeper" und den zusätzlichen Wert 5. Was passiert? Schauen wir mal den Funktionskörper hier an. Hier bilde ich "valSleeper" Per Referenz, Sie sehen es hier und &-Symbol. Das ist der Funktionskörper meines Funktionsobjekts und was tut der Funktionskörper? Er zählt von 0 bis einschließlich 5, schläft aber von der kurzen Zeitraum von Zehntelsekunde und addiert K, K ist 5 hinzu. Nach Adam Riese ist es 1000, hier eben plus 6*5, 1030. Und zum Schluss, damit wir auch noch die ID der Threads sehen, gibt es eine ID auf "std: :cout" raus. Ja, ich denke, nun ist es relativ einfach, was pasieren sollte. Wir erwarten hier für "valSleeper" 1030 und wie erwarten, dass der Thread seine ID ausgibt. Wir lassen das Programm einfach mal laufen und Sie sehen, die Ausgabe ist nicht die Ausgabe, die wir erwartet haben. Was ist Problem? Ich habe hier in dem Programm in zweifacher Hinsicht undefiniertes Verhalten produziert. Erstens, t arbeitet auf "valSleeper", "valSleeper", "valSleeper" sehen Sie hier, Ich nehme das per Referenz an. Der Kinder-Thread arbeitet auf dieser Variable per Referenz schreibt 6*5 drauf und Problem ist, das der Kinder-Thread nicht fertig wird, bevor der Main-Thread hier, sein Gültigkeitsbereich verlässt und das Programm beendet. Das heißt, mein Kinder-Thread hat gar nicht die Zeit, seine Arbeit oder seine Berechnung auszuführen. Zweite Problem ist, mein Kinder-Thread arbeitet auf "std: :cout", sehen Sie es hier, hmm. "Std: :cout" gehört im Main-Thread, das heißt, wenn der Main-Thread out of Scope geht, geht auch "std: :cout" out of Scope. Somit will der Kinder-Thread etwas auf "std: :cout" schreiben, "std: :cout" gibt es aber gar nicht mehr. Wie löse ich das Problem? Relativ einfach, indem ich hier statt "t.detach", "t.join" verwende. Das mache ich hier. Wie hat sich jetzt das Verhalten des Programms geändert? Das Verhalten hat sich insofern geändert, da mein Erzeuger-Thread, durch den Join-Aufruf auf sein Kind wartet, bis eben dieser Thread hier fertig ist. Ja, dann übersetzt ich das mal, hier habe ich es, und führe es aus. Ich muss natürlich erst abspeichern. Und Sie sehen, das richtige Ergebnis "valSleeper=1030" und Sie sehen auch, dass sich die Ausgaben hier "valSleeper" mit der Ausgabe hier überschneiden. Das ist aber eine andere Geschichte, nur so viel vorweg, dass sich die Ausgaben beschneiden ist wohldefiniert, das ist kein kritischer Wettlauf oder ein Data Race. Es ist, so komisch das klingt, nur ein optisches Problem. In dieser Lektion habe ich Ihnen gezeigt, dass der Thread seine Daten per Kopie oder per Referenz annehmen kann. Nimmt der Kinder-Thread seine Daten per Referenz an, müssen Sie sehr aufpassen. Sie müssen insbesondere aufpassen, wenn der Kinder-Thread sich von der Lebenszeit seines Erzeugers trennt, wenn Sie also auf dem Erzeuger-Thread "t.detach" aufrufen.

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!