Assignment Chef icon Assignment Chef
All German tutorials

Programming lesson

Multithreading und Mutexe in C: Black-Friday-Simulation mit pthreads

Lerne in diesem Tutorial, wie du mit C und pthreads eine Black-Friday-Simulation erstellst. Wir erklären Multithreading, Mutexe und die sichere Synchronisation von Threads anhand eines praxisnahen Beispiels aus dem Einzelhandel.

Multithreading C pthreads Tutorial Mutex Beispiel Black Friday Simulation Thread-Synchronisation C Programmierung Betriebssysteme Race Condition vermeiden pthread_mutex_lock Escort Team Simulation Kundenstrom simulieren C Threads Einzelhandel Semaphore vs Mutex Deadlock vermeiden C pthreads Übung Betriebssysteme Aufgabe C POSIX Threads lernen

Einleitung: Black Friday – das Chaos im Elektronikladen meistern

Black Friday ist einer der umsatzstärksten Tage im Jahr. Doch für Ladenbesitzer bedeutet er auch logistische Herausforderungen: Hunderte Kunden strömen gleichzeitig in den Laden, alle wollen zu den begehrten Angeboten in verschiedenen Abteilungen. Wie kann man den Menschenstrom sicher und geordnet lenken? In diesem Tutorial zeigen wir dir, wie du mit C-Programmierung und Multithreading eine Black-Friday-Simulation erstellst, die Kundenströme mithilfe von pthreads und Mutexen verwaltet.

Diese Aufgabe ist typisch für eine Betriebssysteme-Vorlesung und vermittelt grundlegende Konzepte der Thread-Synchronisation. Du lernst, wie du Race Conditions vermeidest und gemeinsame Ressourcen sicher aktualisierst. Stell dir vor, du entwickelst ein Simulationsprogramm für ein Einzelhandels-Szenario – genau das machen wir heute.

Die Ausgangssituation: 500 Kunden, 2 Escort-Teams, 4 Zonen

Unser Szenario: Ein Elektronikladen hat am Black Friday 500 Kunden am Haupteingang (Zone 0). Sie wollen zu vier verschiedenen Abteilungen: Zone 1 (Appliances, 50 Kunden), Zone 2 (TVs, 100 Kunden), Zone 3 (Smartphones, 250 Kunden), Zone 4 (Videospiele, 100 Kunden). Zwei Escort-Teams führen die Kunden in Gruppen zu den Zonen. Team 0 fasst maximal 100 Personen, Team 1 maximal 50. Wichtig: In jeder Zone darf sich immer nur ein Team gleichzeitig aufhalten, um Chaos zu vermeiden. Das ist ein klassisches Synchronisationsproblem, das wir mit Mutexen lösen.

Warum Multithreading? – Die Parallele zu Apps und Live-Events

Stell dir vor, du entwickelst eine Live-Ticker-App für ein großes Sportereignis wie die Fußball-WM oder ein E-Sports-Turnier. Tausende Nutzer greifen gleichzeitig auf die App zu, um aktuelle Scores zu sehen. Jeder Nutzer ist wie ein Thread, der auf eine gemeinsame Datenbank zugreift. Ohne Synchronisation würden Daten inkonsistent werden. Genau so ist es in unserem Laden: Jedes Escort-Team ist ein Thread, und die Zonen sind die gemeinsamen Ressourcen. Mit Mutexen (kurz für „mutual exclusion“) stellen wir sicher, dass immer nur ein Thread auf eine Zone zugreift.

Grundlagen: pthreads und Mutexe in C

In C verwenden wir die POSIX-Thread-Bibliothek (pthreads). Die wichtigsten Funktionen:

  • pthread_mutex_init() – initialisiert einen Mutex
  • pthread_mutex_lock() – sperrt den Mutex (wartet, falls gesperrt)
  • pthread_mutex_unlock() – entsperrt den Mutex
  • pthread_mutex_destroy() – zerstört den Mutex

Ein Mutex ist wie eine virtuelle Tür: Nur ein Thread kann die Tür öffnen und den Raum betreten. Alle anderen warten, bis der Raum wieder frei ist.

Schritt 1: Datenstrukturen und globale Variablen

Wir definieren zunächst die Anzahl der Kunden pro Zone und die Kapazitäten der Teams. Außerdem benötigen wir einen Mutex pro Zone, da jede Zone nur von einem Team gleichzeitig betreten werden darf.

#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>

#define NUM_ZONES 4
#define CUSTOMERS_ZONE1 50
#define CUSTOMERS_ZONE2 100
#define CUSTOMERS_ZONE3 250
#define CUSTOMERS_ZONE4 100

int remaining_customers[NUM_ZONES] = {50, 100, 250, 100};
pthread_mutex_t zone_mutexes[NUM_ZONES];

int team0_capacity = 100;
int team1_capacity = 50;

Schritt 2: Die Thread-Funktion für ein Escort-Team

Jedes Team läuft als eigener Thread. Die Funktion escort_team() nimmt die Team-ID entgegen und bearbeitet solange Zonen, bis alle Kunden bedient sind. Dabei wird pro Zone der Mutex gesperrt, die Kundenanzahl reduziert und der Mutex wieder freigegeben.

void* escort_team(void* arg) {
    int team_id = *(int*)arg;
    int capacity = (team_id == 0) ? team0_capacity : team1_capacity;
    int zone;
    while (1) {
        // Nächste Zone mit wartenden Kunden finden
        zone = -1;
        for (int i = 0; i < NUM_ZONES; i++) {
            if (remaining_customers[i] > 0) {
                zone = i;
                break;
            }
        }
        if (zone == -1) break; // Alle Kunden bedient

        pthread_mutex_lock(&zone_mutexes[zone]);
        if (remaining_customers[zone] > 0) {
            int to_escort = (remaining_customers[zone] < capacity) ? remaining_customers[zone] : capacity;
            remaining_customers[zone] -= to_escort;
            printf("Team %d escortet %d Kunden zu Zone %d. Verbleibend: %d\n", team_id, to_escort, zone+1, remaining_customers[zone]);
        }
        pthread_mutex_unlock(&zone_mutexes[zone]);
    }
    return NULL;
}

Schritt 3: Hauptprogramm – Mutexe initialisieren und Threads starten

Im main() initialisieren wir die Mutexe, erstellen zwei Threads für die Teams und warten auf deren Beendigung. Danach zerstören wir die Mutexe.

int main() {
    pthread_t team0, team1;
    int id0 = 0, id1 = 1;

    // Mutexe initialisieren
    for (int i = 0; i < NUM_ZONES; i++) {
        pthread_mutex_init(&zone_mutexes[i], NULL);
    }

    // Threads erstellen
    pthread_create(&team0, NULL, escort_team, &id0);
    pthread_create(&team1, NULL, escort_team, &id1);

    // Auf Threads warten
    pthread_join(team0, NULL);
    pthread_join(team1, NULL);

    // Mutexe zerstören
    for (int i = 0; i < NUM_ZONES; i++) {
        pthread_mutex_destroy(&zone_mutexes[i]);
    }

    printf("Simulation beendet. Alle Kunden sind in den Zonen.\n");
    return 0;
}

Mögliche Erweiterungen und Fallstricke

Unser einfaches Modell hat eine Schwäche: Beide Teams könnten um dieselbe Zone konkurrieren, aber durch den Mutex wird das verhindert. Allerdings könnte ein Team eine Zone blockieren, während das andere untätig bleibt. Eine fairere Strategie wäre, die Zonen abwechselnd zuzuweisen. Du könntest auch Semaphoren verwenden (sem_init, sem_wait, sem_post), um die Kapazität der Teams zu steuern.

Ein häufiger Fehler ist das Vergessen von pthread_mutex_unlock() – dann kommt es zu einem Deadlock. Teste dein Programm gründlich mit verschiedenen Szenarien. In der Black-Friday-Simulation ist es wichtig, dass die Ausgabe nachvollziehbar ist und keine Kunden verloren gehen.

Zusammenfassung und Ausblick

Mit diesem Tutorial hast du gelernt, wie du Multithreading in C mit pthreads und Mutexen einsetzt, um ein praktisches Problem aus dem Einzelhandel zu simulieren. Diese Konzepte sind grundlegend für die Systemprogrammierung und werden in vielen Bereichen angewendet, von Echtzeitsystemen bis hin zu Webservern. Die Fähigkeit, Thread-Sicherheit zu gewährleisten, ist für jeden C-Entwickler essenziell.

Probiere das Programm aus, erweitere es um eine grafische Ausgabe oder eine Black-Friday-Simulation mit mehreren Läden. Viel Erfolg bei deiner Betriebssysteme-Aufgabe!