Industrielle Fertigung
Industrielles Internet der Dinge | Industrielle Materialien | Gerätewartung und Reparatur | Industrielle Programmierung |
home  MfgRobots >> Industrielle Fertigung >  >> Industrial programming >> C Sprache

C++-Multithreading

Multithreading ist eine spezielle Form von Multitasking und Multitasking ist die Funktion, die es Ihrem Computer ermöglicht, zwei oder mehr Programme gleichzeitig auszuführen. Im Allgemeinen gibt es zwei Arten von Multitasking:prozessbasiert und threadbasiert.

Prozessbasiertes Multitasking behandelt die gleichzeitige Ausführung von Programmen. Thread-basiertes Multitasking befasst sich mit der gleichzeitigen Ausführung von Teilen desselben Programms.

Ein Multithread-Programm enthält zwei oder mehr Teile, die gleichzeitig ausgeführt werden können. Jeder Teil eines solchen Programms wird Thread genannt, und jeder Thread definiert einen separaten Ausführungspfad.

C++ enthält keine integrierte Unterstützung für Multithread-Anwendungen. Stattdessen verlässt es sich vollständig auf das Betriebssystem, um diese Funktion bereitzustellen.

Dieses Tutorial geht davon aus, dass Sie unter Linux OS arbeiten und wir ein Multithread-C++-Programm mit POSIX schreiben werden. POSIX-Threads oder Pthreads bieten APIs, die auf vielen Unix-ähnlichen POSIX-Systemen wie FreeBSD, NetBSD, GNU/Linux, Mac OS X und Solaris verfügbar sind.

Threads erstellen

Die folgende Routine wird verwendet, um einen POSIX-Thread zu erstellen −

#include <pthread.h>
pthread_create (thread, attr, start_routine, arg) 

Hier, pthread_create erstellt einen neuen Thread und macht ihn ausführbar. Diese Routine kann von überall innerhalb Ihres Codes beliebig oft aufgerufen werden. Hier ist die Beschreibung der Parameter −

Sr.No Parameter &Beschreibung
1

Faden

Ein undurchsichtiger, eindeutiger Bezeichner für den neuen Thread, der von der Subroutine zurückgegeben wird.

2

attr

Ein undurchsichtiges Attributobjekt, das zum Festlegen von Threadattributen verwendet werden kann. Sie können ein Thread-Attributobjekt oder NULL für die Standardwerte angeben.

3

start_routine

Die C++-Routine, die der Thread nach seiner Erstellung ausführt.

4

arg

Ein einzelnes Argument, das an start_routine übergeben werden kann. Es muss als Verweis als Zeigerumwandlung vom Typ void übergeben werden. NULL kann verwendet werden, wenn kein Argument übergeben werden soll.

Die maximale Anzahl von Threads, die von einem Prozess erstellt werden können, ist implementierungsabhängig. Einmal erstellt, sind Threads Peers und können andere Threads erstellen. Es gibt keine implizite Hierarchie oder Abhängigkeit zwischen Threads.

Threads beenden

Es gibt folgende Routine, die wir verwenden, um einen POSIX-Thread zu beenden −

#include <pthread.h>
pthread_exit (status) 

Hier pthread_exit wird verwendet, um einen Thread explizit zu verlassen. Typischerweise wird die pthread_exit()-Routine aufgerufen, nachdem ein Thread seine Arbeit beendet hat und nicht länger existieren muss.

Wenn main() vor den Threads, die es erstellt hat, beendet und mit pthread_exit() beendet wird, werden die anderen Threads weiter ausgeführt. Andernfalls werden sie automatisch beendet, wenn main() beendet wird.

Beispiel

Dieser einfache Beispielcode erstellt 5 Threads mit der Routine pthread_create(). Jeder Thread druckt ein "Hello World!" Nachricht und endet dann mit einem Aufruf von pthread_exit().

#include <iostream>
#include <cstdlib>
#include <pthread.h>

using namespace std;

#define NUM_THREADS 5

void *PrintHello(void *threadid) {
   long tid;
   tid = (long)threadid;
   cout << "Hello World! Thread ID, " << tid << endl;
   pthread_exit(NULL);
}

int main () {
   pthread_t threads[NUM_THREADS];
   int rc;
   int i;
   
   for( i = 0; i < NUM_THREADS; i++ ) {
      cout << "main() : creating thread, " << i << endl;
      rc = pthread_create(&threads[i], NULL, PrintHello, (void *)i);
      
      if (rc) {
         cout << "Error:unable to create thread," << rc << endl;
         exit(-1);
      }
   }
   pthread_exit(NULL);
}

Kompilieren Sie das folgende Programm mit der -lpthread-Bibliothek wie folgt −

$gcc test.cpp -lpthread

Führen Sie nun Ihr Programm aus, das die folgende Ausgabe liefert −

main() : creating thread, 0
main() : creating thread, 1
main() : creating thread, 2
main() : creating thread, 3
main() : creating thread, 4
Hello World! Thread ID, 0
Hello World! Thread ID, 1
Hello World! Thread ID, 2
Hello World! Thread ID, 3
Hello World! Thread ID, 4

Argumente an Threads übergeben

Dieses Beispiel zeigt, wie mehrere Argumente über eine Struktur übergeben werden. Sie können jeden Datentyp in einem Thread-Callback übergeben, da er auf void zeigt, wie im folgenden Beispiel erläutert −

#include <iostream>
#include <cstdlib>
#include <pthread.h>

using namespace std;

#define NUM_THREADS 5

struct thread_data {
   int  thread_id;
   char *message;
};

void *PrintHello(void *threadarg) {
   struct thread_data *my_data;
   my_data = (struct thread_data *) threadarg;

   cout << "Thread ID : " << my_data->thread_id ;
   cout << " Message : " << my_data->message << endl;

   pthread_exit(NULL);
}

int main () {
   pthread_t threads[NUM_THREADS];
   struct thread_data td[NUM_THREADS];
   int rc;
   int i;

   for( i = 0; i < NUM_THREADS; i++ ) {
      cout <<"main() : creating thread, " << i << endl;
      td[i].thread_id = i;
      td[i].message = "This is message";
      rc = pthread_create(&threads[i], NULL, PrintHello, (void *)&td[i]);
      
      if (rc) {
         cout << "Error:unable to create thread," << rc << endl;
         exit(-1);
      }
   }
   pthread_exit(NULL);
}

Wenn der obige Code kompiliert und ausgeführt wird, erzeugt er das folgende Ergebnis −

main() : creating thread, 0
main() : creating thread, 1
main() : creating thread, 2
main() : creating thread, 3
main() : creating thread, 4
Thread ID : 3 Message : This is message
Thread ID : 2 Message : This is message
Thread ID : 0 Message : This is message
Thread ID : 1 Message : This is message
Thread ID : 4 Message : This is message

Threads beitreten und trennen

Es gibt folgende zwei Routinen, die wir verwenden können, um Threads beizutreten oder zu trennen −

pthread_join (threadid, status) 
pthread_detach (threadid) 

Die Subroutine pthread_join() blockiert den aufrufenden Thread, bis der angegebene 'threadid'-Thread beendet wird. Wenn ein Thread erstellt wird, definiert eines seiner Attribute, ob er beitreten oder getrennt werden kann. Nur Threads, die als beitretbar erstellt wurden, können beigetreten werden. Wenn ein Thread als getrennt erstellt wird, kann er niemals beigetreten werden.

Dieses Beispiel demonstriert, wie mit der Pthread-Join-Routine auf Thread-Beendigungen gewartet wird.

#include <iostream>
#include <cstdlib>
#include <pthread.h>
#include <unistd.h>

using namespace std;

#define NUM_THREADS 5

void *wait(void *t) {
   int i;
   long tid;

   tid = (long)t;

   sleep(1);
   cout << "Sleeping in thread " << endl;
   cout << "Thread with id : " << tid << "  ...exiting " << endl;
   pthread_exit(NULL);
}

int main () {
   int rc;
   int i;
   pthread_t threads[NUM_THREADS];
   pthread_attr_t attr;
   void *status;

   // Initialize and set thread joinable
   pthread_attr_init(&attr);
   pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);

   for( i = 0; i < NUM_THREADS; i++ ) {
      cout << "main() : creating thread, " << i << endl;
      rc = pthread_create(&threads[i], &attr, wait, (void *)i );
      if (rc) {
         cout << "Error:unable to create thread," << rc << endl;
         exit(-1);
      }
   }

   // free attribute and wait for the other threads
   pthread_attr_destroy(&attr);
   for( i = 0; i < NUM_THREADS; i++ ) {
      rc = pthread_join(threads[i], &status);
      if (rc) {
         cout << "Error:unable to join," << rc << endl;
         exit(-1);
      }
      cout << "Main: completed thread id :" << i ;
      cout << "  exiting with status :" << status << endl;
   }

   cout << "Main: program exiting." << endl;
   pthread_exit(NULL);
}

Wenn der obige Code kompiliert und ausgeführt wird, erzeugt er das folgende Ergebnis −

main() : creating thread, 0
main() : creating thread, 1
main() : creating thread, 2
main() : creating thread, 3
main() : creating thread, 4
Sleeping in thread
Thread with id : 0 .... exiting
Sleeping in thread
Thread with id : 1 .... exiting
Sleeping in thread
Thread with id : 2 .... exiting
Sleeping in thread
Thread with id : 3 .... exiting
Sleeping in thread
Thread with id : 4 .... exiting
Main: completed thread id :0  exiting with status :0
Main: completed thread id :1  exiting with status :0
Main: completed thread id :2  exiting with status :0
Main: completed thread id :3  exiting with status :0
Main: completed thread id :4  exiting with status :0
Main: program exiting.

C Sprache

  1. C++-Operatoren
  2. C++-Kommentare
  3. C++-Klassenvorlagen
  4. C++-Übersicht
  5. C++ Konstanten/Literale
  6. Operatoren in C++
  7. Zahlen in C++
  8. C++-Referenzen
  9. C++-Vorlagen
  10. C++-Multithreading