Article Categories
- All Categories
-
Data Structure
-
Networking
-
RDBMS
-
Operating System
-
Java
-
MS Excel
-
iOS
-
HTML
-
CSS
-
Android
-
Python
-
C Programming
-
C++
-
C#
-
MongoDB
-
MySQL
-
Javascript
-
PHP
-
Economics & Finance
POSIX Threads in OS
POSIX threads (pthreads) are a standardized threading API that allows programs to create multiple concurrent execution paths within a single process. POSIX threads follow the POSIX standard and provide a consistent interface for thread creation, synchronization, and management across Unix-like operating systems including Linux, macOS, and FreeBSD.
Threads enable parallelism by dividing a single task into multiple independent units that can execute simultaneously. POSIX threads are kernel-level threads, meaning they are managed directly by the operating system kernel, which provides better scheduling and true parallelism on multi-core systems.
Thread Fundamentals
A thread is a lightweight process that can run concurrently with other threads within the same process. All threads in a process share the same memory space, including global variables, heap memory, and file descriptors. However, each thread maintains its own stack and program counter, allowing independent execution paths.
POSIX Thread Example
Here's a basic example demonstrating thread creation and execution
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#define NUM_THREADS 5
void *PrintHello(void *threadid) {
long tid;
tid = (long)threadid;
printf("Hello World! It's me, thread #%ld!<br>", tid);
pthread_exit(NULL);
}
int main(int argc, char *argv[]) {
pthread_t threads[NUM_THREADS];
int rc;
long t;
for (t = 0; t < NUM_THREADS; t++) {
printf("In main: creating thread %ld<br>", t);
rc = pthread_create(&threads[t], NULL, PrintHello, (void *)t);
if (rc) {
printf("ERROR; return code from pthread_create() is %d<br>", rc);
exit(-1);
}
}
pthread_exit(NULL);
}
Output
In main: creating thread 0 In main: creating thread 1 Hello World! It's me, thread #0! In main: creating thread 2 In main: creating thread 3 In main: creating thread 4 Hello World! It's me, thread #4! Hello World! It's me, thread #2! Hello World! It's me, thread #1! Hello World! It's me, thread #3!
To compile this program, link with the pthread library
$ gcc -pthread example.c -o example
The pthread_create() function takes four parameters: a pointer to pthread_t (thread ID), thread attributes (NULL for defaults), the start routine function, and arguments to pass to the function. Note that thread execution order is non-deterministic.
Thread Management Functions
POSIX provides several key functions for thread lifecycle management
| Function | Purpose | Description |
|---|---|---|
pthread_join() |
Wait for completion | Blocks until specified thread terminates |
pthread_detach() |
Detach thread | Allows automatic resource cleanup on exit |
pthread_cancel() |
Cancel thread | Requests thread termination |
pthread_exit() |
Exit thread | Terminates calling thread |
Thread Synchronization
Thread synchronization prevents race conditions and ensures data consistency when multiple threads access shared resources.
Mutexes
Mutexes (mutual exclusion) provide exclusive access to shared resources. Only one thread can hold a mutex at a time.
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
int shared_counter = 0;
void *increment_counter(void *arg) {
pthread_mutex_lock(&mutex);
shared_counter++;
printf("Counter: %d<br>", shared_counter);
pthread_mutex_unlock(&mutex);
return NULL;
}
Condition Variables
Condition variables allow threads to wait for specific conditions and signal when conditions change. They work in conjunction with mutexes.
pthread_cond_t condition = PTHREAD_COND_INITIALIZER;
pthread_mutex_t cond_mutex = PTHREAD_MUTEX_INITIALIZER;
// Wait for condition
pthread_mutex_lock(&cond_mutex);
while (condition_not_met) {
pthread_cond_wait(&condition, &cond_mutex);
}
pthread_mutex_unlock(&cond_mutex);
// Signal condition
pthread_mutex_lock(&cond_mutex);
condition_met = 1;
pthread_cond_signal(&condition);
pthread_mutex_unlock(&cond_mutex);
Thread Safety and Deadlock Prevention
Thread safety ensures that shared resources are accessed correctly by multiple threads. Common approaches include
Mutexes Serialize access to critical sections
Atomic operations Indivisible operations that complete without interruption
Thread-local storage Data private to each thread
Deadlock occurs when threads wait indefinitely for each other. Prevention strategies include
Lock ordering Always acquire locks in the same order
Timeout mechanisms Avoid indefinite waiting
Deadlock detection Monitor and break circular dependencies
Conclusion
POSIX threads provide a powerful, standardized API for multi-threaded programming that enables efficient utilization of multi-core processors. With proper synchronization mechanisms and thread management, pthreads allow developers to create scalable, high-performance applications while maintaining portability across Unix-like systems.
