Skip to content

pthread

Networking & ConcurrencyConcurrency / MultithreadingC

What it is

pthread (POSIX Threads) is a standard C library for creating and managing threads. It provides APIs for multithreading, synchronization, and concurrency control in C programs on POSIX-compliant systems.

pthread allows creating multiple threads, synchronizing access to shared resources with mutexes and condition variables, and coordinating execution using thread joins or detachment.

Installation

Usually included in glibc; link with -pthread during compilation

Getting started

The smallest useful thing you can do with it, and what each part means.

Creating and joining a thread
#include <pthread.h>
#include <stdio.h>

void* print_message(void* arg) {
    printf("Hello from thread!\n");
    return NULL;
}

int main() {
    pthread_t thread;
    pthread_create(&thread, NULL, print_message, NULL);
    pthread_join(thread, NULL);
    return 0;
}
Creates a thread that prints a message and waits for it to finish using `pthread_join`.
Using a mutex
#include <pthread.h>
#include <stdio.h>

int counter = 0;
pthread_mutex_t lock;

void* increment(void* arg) {
    pthread_mutex_lock(&lock);
    counter++;
    pthread_mutex_unlock(&lock);
    return NULL;
}

int main() {
    pthread_t threads[10];
    pthread_mutex_init(&lock, NULL);
    for(int i = 0; i < 10; i++) pthread_create(&threads[i], NULL, increment, NULL);
    for(int i = 0; i < 10; i++) pthread_join(threads[i], NULL);
    printf("Counter: %d\n", counter);
    pthread_mutex_destroy(&lock);
    return 0;
}
Demonstrates thread-safe increment of a shared variable using a mutex.

Advanced usage

Where the library earns its place over a simpler alternative.

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

pthread_mutex_t lock;
pthread_cond_t cond;
int ready = 0;

void* wait_thread(void* arg) {
    pthread_mutex_lock(&lock);
    while (!ready) pthread_cond_wait(&cond, &lock);
    printf("Condition met!\n");
    pthread_mutex_unlock(&lock);
    return NULL;
}

void* signal_thread(void* arg) {
    pthread_mutex_lock(&lock);
    ready = 1;
    pthread_cond_signal(&cond);
    pthread_mutex_unlock(&lock);
    return NULL;
}

int main() {
    pthread_t t1, t2;
    pthread_mutex_init(&lock, NULL);
    pthread_cond_init(&cond, NULL);
    pthread_create(&t1, NULL, wait_thread, NULL);
    pthread_create(&t2, NULL, signal_thread, NULL);
    pthread_join(t1, NULL);
    pthread_join(t2, NULL);
    pthread_mutex_destroy(&lock);
    pthread_cond_destroy(&cond);
    return 0;
}
Uses a condition variable to synchronize threads based on a shared condition.
Thread-local storage
#include <pthread.h>
#include <stdio.h>

pthread_key_t key;
void destructor(void* value) { printf("Thread-specific data freed\n"); }

void* thread_func(void* arg) {
    pthread_setspecific(key, arg);
    printf("Thread data: %s\n", (char*)pthread_getspecific(key));
    return NULL;
}

int main() {
    pthread_key_create(&key, destructor);
    pthread_t thread;
    char* msg = "Hello Thread";
    pthread_create(&thread, NULL, thread_func, msg);
    pthread_join(thread, NULL);
    pthread_key_delete(key);
    return 0;
}
Demonstrates storing and accessing thread-specific data using pthread keys.

Errors and fixes

The failures you are most likely to hit, and what actually resolves them.

EDEADLK
Occurs when a deadlock is detected. Ensure consistent locking order or use `pthread_mutex_trylock`.
EINVAL
Indicates invalid arguments passed to pthread functions. Verify thread, mutex, and condition variable initialization.
ENOMEM
Insufficient memory to create a new thread. Consider limiting thread creation or using a thread pool.

Best practices

  • Always initialize and destroy mutexes and condition variables properly.
  • Avoid deadlocks by locking mutexes in a consistent order.
  • Use `pthread_join` or detach threads to manage their lifecycle.
  • Minimize the work done while holding a mutex to reduce contention.
  • Prefer thread-local storage for data specific to a thread.

Background

Why it exists, and what it was reacting to.

pthread was developed as part of the POSIX standard to allow portable multithreaded programming in C. It provides primitives for thread creation, joining, mutexes, condition variables, and thread-local storage, enabling developers to write efficient concurrent programs.