C++: Multithreading

Thread versus Task

LinkedIn Learning kostenlos und unverbindlich testen!

Jetzt testen Alle Abonnements anzeigen
Threads und Tasks sind zwei Möglichkeiten, um in C++ Threads zu verwalten. Worin der Unterschied liegt, verrät dieser Film.
05:50

Transkript

Um Tasks besser zu verstehen, will ich in dieser Lektion Threads-Tasks gegenüber stellen. Hier haben Sie ein Thread. Was tut der Thread? Dieser Thread t verwendet die Variable res per Reference und addiert die Werte von 3 bis 4 zusammen, schreibt sie nach res. Und damit ist Ergebnis in dem Aufruf oder Erzeugnis-Thread verfügbar, weil res in dem aufgerufenen Thread per Reference verwendet wurde. Durch die join() wartet der Erzeuger, dieser ganze Thread, drauf, bis sein Kind-Thread fertig ist, bis er seine aufwendige Kalkulation vollzogen hat. Was ist der Unterschied zum Task? Dieser Task tut semantisch das Gleiche. Hier habe ich den Aufruf async, und in diesem async-Aufruf verwende ich eine Lambda-Funktion, die das Ergebnis von 3+4, sprich 7, zurückgibt. Hier habe ich nun Future. Und mit fut.get() frage ich das Ergebnis dieser Kalkulation ab. Das ist std::async, das ist die Ausprägung vom Task oder vom Promise oder Future. Hier ist die rechte Seite der Promise und die linke Seite, fut, der Future. Die beiden Komponenten sind mit dem Datenkanl verbunden. Und mit fut.get() können Sie das Ergebnis von dieser Kalkulation hier abfragen. Ja, und so will ich gern das noch mal in der Tabelle vergleichen. Header-Datei, okey, das ist einfach. Der Thread benötigt die Header-Datei . Future benötigt die Header-Datei oder auch std::async. Beteiligten. Hier wird es schon deutlich unterschiedlicher. Der Beteiligte hier ist Erzeuger-Thread oder Kinder-Thread. Und hier sind es zwei Endpunkte des Datenkanals – Promise und Future. Promise, Future. Dann die Kommunikation. Die Kommunikation hier geschieht über eine geschärte Variable res, das ist eine geteilte Variable. Die sowohl der Erzeuger kennt, die auch der Kinder-Thread kennt. Hier geschieht es über einen Kommunikationskanal. Dieser Kommunikationskanal wird durch den Aufruf async aufgemacht. Und damit sind fut und async miteinander verbunden. Thread-Erzeugung. Hier wird immer ein Thread erzeugt. Genau, weil ich hier explizit sage thread t. Hier kann, muss aber kein Thread erzeugt werden. Das liegt in der Kontrolle des Systems, also in der C++-Laufzeit. Das System entscheidet, ob es Sinn macht, hier einen eigenen Thread zu starten, oder, weil die Aufgabe so einfach ist, diese Aufgabe mit dem gleichen Prozess auszuführen. Weitere Gründe, dafür ein Thread zu starten, können sein, wie ist die Auslastung auf Ihrem System, wie viel Cores, wie viel Kerne besitzen Sie, alles Entscheidungen, die durch die C++-Laufzeit getroffen werden. Sie denken hier nicht an Threads, Sie denken hier nur an Arbeitspaketen, Aufgaben, die es zu erledigen gilt, und Sie überlassen dem System, wie diese Aufgaben auf verschiedene Threads verteilt werden. Thread-Erzeugung ist hier also verbindlich, hier sage ich es explizit. Hier ist es optional. Synchronisation, durch diesen join-Aufruf wartet der Erzeuger-Thread auf sein Kind. Und hier ist der fut.get()-Aufruf blockierend. Das heißt, wenn es Ergebnis von 3+4 hier noch nicht zur Verfügung steht, wartet der Future noch so lang bis es eben da ist. Und interessant ist es auch, wenn Sie eine Ausnahme im Kind-Thread hier haben. Wenn Sie eine Ausnahme im Kind-Thread hier haben, stimmt der Kind-Thread, stimmt der Mensch-Thread, stimmt das ganze Programm. Wenn Sie eine Ausnahme in async haben, was passiert dann? Dann bekommt der Future die Ausnahme als Rückgabewert von async, und er muss natürlich mit der Ausnahme umgehen können, indem er sie fängt. Nun will ich gern noch std::async an einem Beispielchen genauer vorstellen. Schon geht es los mit dem Beispiel. Ich verwende dreimal den Aufruf std::async, einmal, zweimal, dreimal. Im ersten Aufruf führe ich eine Funktion auf, helloFunction(). Diese Funktion erwartet ein Argument per Reference. Und dann hier erhält die Funktion ein Argument. Also führe ich in std::async die Funktion helloFunction() mit dem Argument „function“ aus. Im zweiten Fall verwende ich hier ein Funktionsobjekt. Und Argument ist in diesem Fall der String „function object“. Im dritten Fall sieht es ein bisschen verwirrend aus. Hier steht ein Arbeitspacket, das std::async zu erledigen hat, die Lambda-Funktion. Und diese Lambda-Funktion benötigt als Argument einen String, und der String heißt natürlich jetzt „lambda function“. Ja, das war es schon. Hier unten wird der erste Future sein Ergebnis abholen, der zweite Future und der dritte Future. Und jetzt fehlt eigentlich nur noch, dass ich das Programm ausführe. Und Sie sehen, das Programm gibt immer das gleiche Ergebnis, weil ich die Future natürlich in der gewissen Sequenz hintereinander ausführe. In dieser Lektion habe ich Ihnen Threads und Tasks gegenüber gestellt und zum Schluss gezeigt, wie Sie Task in der Form von std::async einfach anwenden können.

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!