Linux System Programming · intermediate · ~12 min

Mutexes — pthread_mutex_t

Protect shared state with a mutex so that only one thread can change it at a time.

Lesson

What a mutex is

A mutex (short for mutual exclusion lock) makes sure that only one thread at a time can enter a critical section — a region of code that touches shared data.

The pattern is always the same:

lock → modify shared state → unlock

pthread_mutex_t m = PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_lock(&m);
/* … exactly one thread is here … */
pthread_mutex_unlock(&m);

While one thread holds the lock, any other thread that calls pthread_mutex_lock waits until the lock is released.

Rules to follow

  • Lock before every read and every write of the shared variable. Reading without the lock can return a torn value — a half-updated value caught mid-change.
  • Unlock on every exit path, including error paths. A forgotten unlock leaves the lock held forever, which causes a deadlock (other threads wait forever).
  • Hold the lock for as little code as possible. While a mutex is held, every other thread that needs it is blocked.
  • Call pthread_mutex_destroy when you are done with a mutex that you allocated on the heap.

Code examples

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

static long counter = 0;
static pthread_mutex_t m = PTHREAD_MUTEX_INITIALIZER;

static void *bump(void *_) {
    (void)_;
    for (long i = 0; i < 1000000; i++) {
        pthread_mutex_lock(&m);
        counter++;
        pthread_mutex_unlock(&m);
    }
    return NULL;
}

int main(void) {
    pthread_t a, b;
    pthread_create(&a, NULL, bump, NULL);
    pthread_create(&b, NULL, bump, NULL);
    pthread_join(a, NULL); pthread_join(b, NULL);
    printf("counter = %ld\n", counter);
    return 0;
}

Common mistakes

  • Forgetting to unlock on an error or early-return path. Centralize the unlock with a small wrapper function or a single goto cleanup; label so every exit goes through the same code.
  • Holding the lock across a long system call (for example, a read on a socket). Every other thread stalls while you wait. Do the slow work outside the locked region.

Summary

  • A pthread_mutex_t guards a critical section so only one thread runs it at a time.
  • Always follow the lock → modify → unlock pattern.
  • Hold the lock for as little code as possible.
  • Forgetting to unlock causes a deadlock.

Practice with these exercises