Um den wechselseitigen Zugriff auf Ressourcen (z.B. Datenbankzeilen) zu Synchronisieren verwendet man Mutual Exclusion (Mutex).
Vorgehen
- Anlegen und Initialisieren von Mutexvariablen mit pthread_mutex_init
- Vor dem Eintritt in einen kritischen Bereich Sperre anfordern mit pthread_mutex_lock (Polling)
- Nach Abarbeitung des kritischen Bereichs Sperre freigeben mit pthread_mutex_unlock
Zur Threadkoordination (ohne Polling) kann
- pthread_cond_init eine Condition-Variable anlegen
- Mittels pthread_cond_wait wird auf eine Kondition gewartet
- Benachrichtigungen über Statusänderungen werden mittels pthread_cond_signal bzw. pthread_cond_broadcast versandt
- Die Warteschlange wird im FIFO-Prinzip abgearbeitet
- Zur Identifikation und zum Vergleich von Threads stehen die Funktionen pthread_self und pthread_equal zur Verfügung
Beispiel
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
int arrived = 0;
pthread_mutex_t taxi;
pthread_cond_t station;
void *taxiDriver(void *p) {
int i;
for (i = 0; i < 3; ++i) {
// Sperrt das Taxi, damit während dem kritischen Zustand
// (Taxi fahren) niemand was anderes mit dem Taxi macht
pthread_mutex_lock(&taxi);
printf("Mein Taxi fährt\n");
sleep(1);
// Kritisch! Nach jedem Ausdruck kann der Scheduler
// den Thread unterbrechen. Wenn taxiGuest genau zwischen
// der Abfrage `i > 1` und dem schreiben von `arrived`
// den Inhalt von `arrived` ausliest, kommt es vor, dass
// er denkt er wäre nicht angekommen obwohl die Bedingung
// wahr war. Deswegen Taxi sperren!
if (i > 1)
arrived = 1;
pthread_cond_signal(&station);
// Nach dem sperren nicht vergessen dass man die Ressource
// auch wieder freigeben muss
pthread_mutex_unlock(&taxi);
}
}
void *taxiGuest(void *p) {
printf("Der Fahrgast entspannt sich...\n");
sleep(1);
pthread_mutex_lock(&taxi);
while (arrived == 0)
pthread_cond_wait(&station, &taxi);
printf("Der Fahrgast öffnet die Tür\n");
sleep(1);
printf("Der Fahrgast steigt aus\n");
pthread_mutex_unlock(&taxi);
}
int main(int argc, char **argv) {
pthread_t driver, guest;
pthread_mutex_init(&taxi, NULL);
pthread_cond_init(&station, NULL);
pthread_create(&driver, NULL, taxiDriver, NULL);
pthread_create(&guest, NULL, taxiGuest, NULL);
pthread_join(guest, NULL);
pthread_join(driver, NULL);
pthread_mutex_destroy(&taxi);
pthread_cond_destroy(&station);
return 0;
}