Linux System Programming · intermediate · ~25 min
Spawn threads, share state via mutex, signal via condition variable.
pthreads spawn lightweight execution contexts that share memory. You guard shared state with mutexes and coordinate via condition variables.
Multi-threaded C is everywhere — server worker pools, GUI event loops, parallel data crunching. Pthreads is the C-language API.
create + join. pthread_create(&tid, attr, fn, arg) spawns; pthread_join(tid, &ret) waits.
Mutex. pthread_mutex_lock/unlock. Holds for the critical section. PTHREAD_MUTEX_INITIALIZER is the static init.
Condition variable. Wait under a lock; another thread signals. The signal+wait pair is how producer/consumer queues work.
Detached threads. pthread_detach(tid) says 'I don't care about the return; reclaim immediately on exit'.
Pentester mindset. Race conditions in concurrent code are CVEs. A 'check then act' across threads without a mutex is a TOCTOU at thread level.
Defensive coding habit. Always check the return of pthread_* functions. Always pair lock with unlock. Use pthread_mutex_destroy at teardown.
#include <pthread.h>
int pthread_create(pthread_t *tid, const pthread_attr_t *attr, void *(*fn)(void *), void *arg);
int pthread_join(pthread_t tid, void **retval);
int pthread_mutex_lock(pthread_mutex_t *m);
int pthread_cond_wait(pthread_cond_t *c, pthread_mutex_t *m);
POSIX threads (pthreads) are the standard C concurrency API on Linux.
You create with pthread_create, join with pthread_join, protect shared
state with pthread_mutex_t, and signal between threads with
pthread_cond_t.
pthread_mutex_t m = PTHREAD_MUTEX_INITIALIZER;
int counter = 0;
void *bump(void *_) {
pthread_mutex_lock(&m);
counter++;
pthread_mutex_unlock(&m);
return NULL;
}
pthread_t t;
pthread_create(&t, NULL, bump, NULL);
pthread_join(t, NULL);
pthread_mutex_lock(&m); /* acquire */
while (!queue_has_data(q)) /* spurious wakeups exist */
pthread_cond_wait(&c, &m); /* atomic release + wait */
item_t x = queue_pop(q);
pthread_mutex_unlock(&m); /* release */
use(x);
ThreadSanitizer (-fsanitize=thread) finds data races at runtime. gdb info threads lists all threads; thread N switches.
All threads share the heap. Anything shared must be guarded. volatile is NOT a substitute for a mutex or atomic.
nginx (limited use), redis (limited), most C++ projects, every C database driver. Anywhere C-language concurrency lives.
create + join + mutex + cond. Guard every shared read and write. Pair lock with unlock.