POSIX Threads
POSIX Threads (commonly referred to as pthreads) is a standardized C/C++ execution model defined by IEEE POSIX 1003.1c. It provides an API for creating, controlling, and synchronizing parallel threads of execution within a single process.
In Unix-like systems (such as Linux and macOS), pthreads is the standard execution model for lightweight multi-threading.
Core Execution Model
Unlike separate processes (created via fork()), threads within the same process share:
- Address Space: Global variables, static data, and heap memory.
- File Descriptors: Open files, sockets, and pipes.
- Process Context: User/group IDs, signal handlers, and current working directory.
Each thread maintains its own independent execution state, consisting of:
- A unique Thread ID (
pthread_t). - A private Stack Frame for local variables and function calls.
- A dedicated set of Registers (including Program Counter and Stack Pointer).
Key API Primitives
The C API exposed in <pthread.h> centers around four primary abstractions:
Thread Management
pthread_create(): Spawns a new execution thread to run a designated start routine.pthread_join(): Blocks the calling thread until a target thread terminates (reaping its return status).pthread_detach(): Releases thread resources automatically upon exit without requiring apthread_join.pthread_exit(): Terminates the calling thread without exiting the entire process.
Synchronization Primitives
Because threads share memory, synchronization mechanisms prevent race conditions:
| Primitive | Type | Primary Functions | Use Case |
|---|---|---|---|
| Mutex | pthread_mutex_t |
pthread_mutex_lock(), pthread_mutex_unlock() |
Mutual exclusion for critical sections accessing shared data. |
| Condition Variable | pthread_cond_t |
pthread_cond_wait(), pthread_cond_signal() |
Signaling state changes or events between threads. |
| Read-Write Lock | pthread_rwlock_t |
pthread_rwlock_rdlock(), pthread_rwlock_wrlock() |
Concurrent readers or exclusive writer pattern. |
| Barrier | pthread_barrier_t |
pthread_barrier_wait() |
Synchronizing a fixed number of threads at a execution checkpoint. |
Minimal Code Example
#include <stdio.h>
#include <pthread.h>
void* worker(void* arg) {
long id = (long)arg;
printf("Hello from thread %ld\n", id);
return NULL;
}
int main(void) {
pthread_t thread;
// Spawn thread running worker(1)
pthread_create(&thread, NULL, worker, (void*)1);
// Wait for thread completion
pthread_join(thread, NULL);
return 0;
}
Where is it used?
Linux (NPTL)
On modern Linux, pthreads is implemented via the Native POSIX Thread Library (NPTL):
- Under the hood,
pthread_create()invokes theclone()system call with flagsCLONE_VM,CLONE_FS,CLONE_FILES, andCLONE_SIGHAND. - The Linux kernel treats threads as Light-Weight Processes (LWPs), scheduling them alongside standard processes using the same Completely Fair Scheduler (CFS).
- Synchronization constructs like
pthread_mutex_tutilize futex (fast userspace mutex) system calls to avoid kernel context switches when there is no lock contention.
Because pthreads is an IEEE POSIX standard, it is natively available on almost every UNIX-like operating system, mobile OS, and real-time system in existence.
Apple Ecosystem (macOS, iOS, iPadOS, watchOS)
Apple’s core operating system layer (Darwin) is POSIX-compliant.
- Under the Hood: Apple’s higher-level concurrency tools—like
DispatchQueue(Grand Central Dispatch/GCD) and Swift Concurrency—are built on top of Mach threads and pthreads. - Direct C/C++ Access: You can include
<pthread.h>directly in Xcode and write raw pthread calls in C, C++, or Objective-C on any Apple device.
The BSD Family (FreeBSD, OpenBSD, NetBSD)
The open-source BSD family (which shares common heritage with UNIX) uses pthreads as its primary threading API.
- FreeBSD: Implements pthreads via
libpthread, mapping threads directly to kernel-schedulable execution units (1:1threading model). - OpenBSD / NetBSD: Use their own clean implementations of
<pthread.h>for portable multithreading.
Commercial Unix Systems
Enterprise UNIX platforms rely heavily on pthreads for backwards compatibility and high-performance multi-socket scaling:
- Oracle Solaris (formerly SunOS): Supported both "Solaris UI Threads" and pthreads, but pthreads became the primary system standard.
- IBM AIX: Uses pthreads natively for IBM Power systems architecture.
- HP-UX: Hewlett-Packard’s enterprise UNIX platform.
Mobile Operating Systems
- Android: Although Android uses the Linux kernel, its C standard library (Bionic) provides its own lightweight implementation of
<pthread.h>. Native code compiled with the Android NDK relies on pthreads for multithreading.
Real-Time & Embedded Operating Systems (RTOS)
Many industrial and automotive systems implement the POSIX pthreads spec so embedded developers can write standard C without learning proprietary APIs:
- QNX Neutrino: A microkernel RTOS widely used in automotive infotainment, medical devices, and avionics. QNX uses pthreads as its standard C thread model.
- VxWorks: A major industrial RTOS that includes a POSIX compliance layer providing
pthread_createand POSIX mutexes. - FreeRTOS / Zephyr: Small microcontroller operating systems often provide optional POSIX Abstraction Layers, enabling
pthreadAPI calls on tiny hardware like ESP32 or ARM Cortex-M chips.
What About Windows?
Windows does not use pthreads natively—it has its own proprietary threading API (CreateThread, InitializeCriticalSection).
However, pthreads is often used on Windows through wrapper layers:
- POSIX Compatibility Layers: Environments like MinGW-w64 (
winpthreads) or Cygwin translate POSIXpthread_*calls into native Win32 API calls. - WSL (Windows Subsystem for Linux): Runs native Linux binaries directly, which run standard Linux NPTL pthreads.
