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

C++ Multithreading meistern: Effiziente nebenläufige Programmierung mit POSIX Threads

Grundlagen: Multitasking vs. Multithreading

Multithreading ist eine spezialisierte Form des Multitaskings. Während prozessbasiertes Multitasking die gleichzeitige Ausführung eigenständiger Programme verwaltet, ermöglicht threadbasiertes Multitasking die nebenläufige Ausführung verschiedener Teile desselben Programms.

Ein multithreaded Programm besteht aus zwei oder mehr Threads, die parallel laufen können. Jeder Thread definiert einen eigenen Ausführungspfad. C++ (vor C++11) bietet keine eingebaute Thread-Unterstützung, sondern greift vollständig auf das Betriebssystem zurück. Dieses Tutorial nutzt POSIX Threads (pthreads), die auf Linux, macOS, FreeBSD, Solaris und anderen Unix-ähnlichen Systemen verfügbar sind.

Threads erstellen: pthread_create()

#include <pthread.h>
int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
                   void *(*start_routine)(void *), void *arg);
Parameter Beschreibung
thread Zeiger auf pthread_t; erhält die eindeutige Thread-ID.
attr Attribut-Objekt für Thread-Eigenschaften (z. B. Joinable/Detached), oder NULL für Standardwerte.
start_routine Funktionszeiger auf die Thread-Startfunktion (Signatur: void* func(void*)).
arg Einzelnes Argument, das an start_routine übergeben wird (als void*).

Threads sind Peers – es gibt keine Hierarchie. Jeder Thread kann weitere Threads erzeugen.

Threads beenden: pthread_exit()

void pthread_exit(void *retval);

Beendet den aufrufenden Thread explizit. Wenn main() vor seinen Child-Threads endet und pthread_exit() aufruft, laufen die anderen Threads weiter. Andernfalls werden sie beim Beenden von main() automatisch terminiert.

Beispiel: 5 Threads erzeugen und beenden

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

using namespace std;
#define NUM_THREADS 5

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

int main() {
    pthread_t threads[NUM_THREADS];
    int rc;
    for (int i = 0; i < NUM_THREADS; ++i) {
        cout << "main(): erzeuge Thread " << i << endl;
        rc = pthread_create(&threads[i], NULL, PrintHello, (void*)i);
        if (rc) {
            cerr << "Fehler: Thread-Erstellung fehlgeschlagen, Code " << rc << endl;
            exit(-1);
        }
    }
    pthread_exit(NULL); // Wartet nicht auf Threads, lässt sie aber laufen
    return 0;
}

Kompilieren: g++ -o thread_demo thread_demo.cpp -lpthread

Argumente an Threads übergeben

Da start_routine ein void* erwartet, können Sie beliebige Daten über eine Struktur übergeben:

struct ThreadData {
    int thread_id;
    const char* message;
};

void* PrintHello(void* arg) {
    ThreadData* data = static_cast<ThreadData*>(arg);
    cout << "Thread ID: " << data->thread_id
         << ", Nachricht: " << data->message << endl;
    pthread_exit(NULL);
}

Threads joinen und detach'en

Zwei zentrale Routinen steuern den Lebenszyklus:

Beispiel: pthread_join() für synchrones Warten

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

using namespace std;
#define NUM_THREADS 5

void* wait(void* t) {
    long tid = (long)t;
    sleep(1);
    cout << "Thread " << tid << " beendet sich." << endl;
    pthread_exit(NULL);
}

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

    pthread_attr_init(&attr);
    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);

    for (int i = 0; i < NUM_THREADS; ++i) {
        pthread_create(&threads[i], &attr, wait, (void*)i);
    }
    pthread_attr_destroy(&attr);

    for (int i = 0; i < NUM_THREADS; ++i) {
        pthread_join(threads[i], &status);
        cout << "Main: Thread " << i << " beendet mit Status " << status << endl;
    }
    cout << "Main: Programmende." << endl;
    pthread_exit(NULL);
}

Moderne Alternative: C++11 <thread>

Seit C++11 bietet die Standardbibliothek plattformunabhängige Thread-Unterstützung (std::thread, std::mutex, std::condition_variable, …). Für neue Projekte wird die Nutzung der C++-Standardbibliothek empfohlen, da sie typsicherer und portabler ist.

C Sprache

  1. C++-Operatoren meistern: Ein vollständiger Leitfaden mit praktischen Beispielen
  2. C++-Kommentare: Best Practices für lesbaren, wartbaren Code
  3. C++ Klassentemplates meistern: Ein praktischer Leitfaden
  4. C++ Programmiersprache: Überblick & Kernfeatures
  5. C++ Konstanten & Literale: Typen, Syntax & Best Practices
  6. C++ Operatoren: Typen, Nutzung & Best Practices
  7. C++ Numerische Typen: Praktischer Leitfaden
  8. C++ Referenzen: Konzepte & Unterschiede zu Pointern
  9. C++ Templates: Generische Programmierung meistern
  10. C++ Multithreading meistern: Effiziente nebenläufige Programmierung mit POSIX Threads