Threads erzeugen

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.

 

 

 

Kommentare   

0 #1 Enrico Weigelt 2016-07-07 12:48
hmm, mit Lambdas fängt das ganze langsam an, ein wenig Sinn zu ergeben - ansonsten eher verzichtbar.

Jetzt sollte man einigen Leuten nur noch beibringen, daß man nicht gedankenlos von std::thread ableiten, sondern - wie in Deinem Beispiel - nur Threads innerhalb anderer Objekte erzeugen sollte.

Aber nach wie vor ärgert es mich richtig, daß man (AFAIK) immernoch keine Thread-Namen setzen kann.

Ergo bleib ich doch lieber beim altbewährten pthread.


--mtx
Zitieren
0 #2 Www.e-ukraina.pl 2016-09-05 07:18
An impressive share! I'νe јust forwarded tɦis onjto a friend
who Һаѕ bееn conducting a ittle homework on this.

And he in fact ordeгeԀ me dinner due to thе fɑct that I foᥙnd iit fⲟr
him... lol. Ꮪo alⅼow mе tߋ reword thiѕ.... Ƭhank YOU for the meal!!
But yeah, tһanks fⲟr spending tіme to talk abοut tҺis subject Һere on your blog.
Zitieren

Kommentar schreiben


Modernes C++

Abonniere den Newsletter

Inklusive zwei Artikel meines Buchs
Introduction und Multithreading

Beiträge-Archiv

Sourcecode

Neuste Kommentare