Inhaltsverzeichnis[Anzeigen]

Der Umgang mit Threads in C++ ist schnell erzählt. Durch den Aufruf std::thread wird ein neuer Thread erzeugt. Dieser Thread benötigt ein Arbeitspaket und startet sofort. Der erzeugende Thread (Der Erzeuger) muss sich um die Lebenszeit seines erzeugten Threads (Das Kind) kümmern. Der Erzeuger wartet entweder, bis sein Kind seine Arbeit vollzogen hat oder er trennt sich von ihm. Die Daten nimmt das Kind per Copy oder Referenz an. 

Nach diesem Schnelldurchlauf folgen nun die einzelnen Punkte im Detail.

Einen Thread erzeugen und ausführen 

Nun ein bisschen formaler. Ein Thread als ausführbare Einheit (thread of execution) enthält seine aufrufbare Einheit und startet diese sofort.

Dieser Satz benötigt ein paar Erläuterungen:

  • Eine aufrufbare Einheit ist alles, was sich wie eine Funktion verhält. Das ist typischerweise eine Funktion, ein Funktionsobjekt oder eine  Lambda-Funktion.
  • Ein Funktionsobjekt ist eine Instanz einer Klasse, für die der Klammeroperator überladen wurde. Der wesentliche Unterschied von Funktionen zu Funktionsobjekten ist, das Funktionsobjekte Zustand besitzen können.
  • Eine Lambda-Funktion (anonymous function) ist ein nackter Funktionskörper, der keinen Namen besitzt. Sie kann direkt dort verwendet werden, wo sie benötigt wird. Schließen Lambda-Funktionen ihren Aufrufkontext ein, werden sie gerne Closure genannt. 

Nach der Theorie ein kleines Beispiel.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
#include <iostream>
#include <thread>

void helloFunction(){
  std::cout << "Hello C++11 from a function." << std::endl;
}

class HelloFunctionObject  {
  public:
    void operator()() const {
      std::cout << "Hello C++11 from a function object." << std::endl;
    }
};

int main(){

  std::cout << std::endl;

  // thread executing helloFunction
  std::thread t1(helloFunction);

  // thread executing helloFunctionObject
  HelloFunctionObject helloFunctionObject;
  std::thread t2(helloFunctionObject);

  // thread executing lambda function
  std::thread t3([]{std::cout << "Hello C++11 from lambda function." << std::endl;});

  // ensure that t1, t2 and t3 have finished before the main thread terminates
  t1.join();
  t2.join();
  t3.join();

  std::cout << std::endl;

};

 

Sowohl Thread t1 als auch Thread t2 und t3 geben ihre Nachricht auf der Konsole aus. Das Arbeitspaket des Threads t2 ist ein Funktionsobjekt (Zeile 8 - 13), das des Threads t3 eine Lambda-Funktion (Zeile 27).  Zuletzt wartet der Erzeugerthread oder auch der main-Thread in den Zeilen 30 - 32 darauf, bis seine Kinder fertig sind.

Interessanter ist da schon die Ausgabe des Programms.

createThread

Die zwei Programmausführungen unterscheiden sich in zweifacher Hinsicht. Zum einen werden die Kinderthreads in den zwei Durchläufen in verschiedenen Reihenfolgen ausgeführt, zum andern ist die Ausgabe der Threads verschränkt. So wird im zweiten Durchlauf der Zeilenumbruch der Funktion helloFunktion erst nach  der Lambda-Funktion ausgegeben.

Weiter geht's im nächsten Artikel mit der Lebenszeit von Threads.

Hintergrundwissen

Aufrufbare Einheiten und Lambda-Funktionen

Die Details rund um aufrufbare Einheiten und insbesondere Lambda-Funktionen sind in meinen Linux-Magazin Artikel 1 und 2 erklärt. Zu einfachsten sind diese unter http://www.grimm-jaud.de/index.php/modernes-c-in-der-praxis-linux-magazin-a zu finden.

 

 

 

 

 

 

title page smalltitle page small Go to Leanpub/cpplibrary "What every professional C++ programmer should know about the C++ standard library".   Hole dir dein E-Book. Unterstütze meinen Blog.

 

 

 


Mentoring

Stay Informed about my Mentoring

 

Rezensionen

Tutorial

Besucher

Heute 335

Gestern 1228

Woche 4216

Monat 23003

Insgesamt 3875717

Aktuell sind 32 Gäste und keine Mitglieder online

Kubik-Rubik Joomla! Extensions

Abonniere den Newsletter (+ pdf Päckchen)

Beiträge-Archiv

Sourcecode

Neuste Kommentare