pthread

Language: C

Concurrency / Multithreading

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.

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.

Installation

linux: Usually included in glibc; link with -pthread during compilation
mac: Included by default; link with -pthread
windows: Use pthreads-w32 library: http://sourceware.org/pthreads-win32/

Usage

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

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.

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.

Error Handling

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.