Fundamentals 21 min read

An Introduction to POSIX Threads (Pthread) and Their Practical Usage in C/C++

This article provides a comprehensive overview of POSIX threads, covering their architecture, creation, synchronization, attributes, scheduling policies, advantages, drawbacks, and real‑world examples such as mutex protection, barrier synchronization, and a cross‑platform network server implementation.

Deepin Linux
Deepin Linux
Deepin Linux
An Introduction to POSIX Threads (Pthread) and Their Practical Usage in C/C++

In the world of programming, multithreading acts like a magical key that unlocks efficient processing and resource utilization, and Pthread (POSIX threads) stands out as a brilliant gem for implementing multithreaded applications on Linux, Unix, macOS, and even Windows via compatibility layers.

1. Introduction to Pthread

Pthread is the POSIX standard thread library that offers a powerful and portable set of APIs for creating, managing, and synchronizing threads across many operating systems, including Unix‑like systems and Windows (through ports such as pthreads‑win32).

The API follows familiar C/C++ naming conventions; for example, pthread_create creates a new thread and takes parameters for thread ID, attributes, start routine, and arguments, allowing fine‑grained control over thread creation.

2. Specific Usage of Pthread

2.1 Creating Threads

The primary way to create a thread is via pthread_create . Its prototype is:

int pthread_create(pthread_t *restrict tidp, const pthread_attr_t *restrict attr, void *(*start_rtn)(void *), void *restrict arg);

Example code:

#include
#include
#include
#include
#include
pthread_t ntid;
void printids(const char *s){
    pid_t pid = getpid();
    pthread_t tid = pthread_self();
    printf("%s pid %u tid %u (0x%x)\n", s, (unsigned int)pid, (unsigned int)tid, (unsigned int)tid);
}
void *thr_fn(void *arg){
    printids("new thread: ");
    return NULL;
}
int main(void){
    int err = pthread_create(&ntid, NULL, thr_fn, NULL);
    if (err != 0) printf("can't create thread: %s\n", strerror(err));
    printids("main thread:");
    sleep(1);
    exit(0);
}

2.2 Thread Blocking and Exit

pthread_join blocks the calling thread until the specified thread terminates, returning the thread’s exit status:

#include
#include
void* thread_main(void* pmax){
    int max = *((int*)pmax);
    for(int i=0;i

pthread_exit terminates the calling thread and makes its argument available to a joining thread.

2.3 Obtaining Thread Identifiers

pthread_self returns the calling thread’s ID, useful for distinguishing threads in concurrent code.

#include
#include
#include
#include
#include
pthread_t ntid;
void printids(const char *s){
    pid_t pid = getpid();
    pthread_t tid = pthread_self();
    printf("%s pid %u tid %u (0x%x)\n", s, (unsigned int)pid, (unsigned int)tid, (unsigned int)tid);
}
int main(void){
    printids("main thread:");
    return 0;
}

3. Pthread Thread Attributes

3.1 Detach State

Threads are joinable by default; they can be created as detached either by setting the attribute before pthread_create or by calling pthread_detach after creation.

pthread_t tid;
pthread_attr_t attr;
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
pthread_create(&tid, &attr, THREAD_FUNCTION, arg);

Or:

pthread_t thread_id;
pthread_create(&thread_id, NULL, thread_function, NULL);
pthread_detach(thread_id);

3.2 Priority Adjustment

Thread priority can be set with pthread_attr_setschedparam when using real‑time scheduling policies (SCHED_FIFO or SCHED_RR). The priority range can be queried with sched_get_priority_min and sched_get_priority_max .

pthread_attr_t attr;
struct sched_param param;
pthread_attr_init(&attr);
pthread_attr_setschedpolicy(&attr, SCHED_FIFO);
int min = sched_get_priority_min(SCHED_RR);
int max = sched_get_priority_max(SCHED_RR);
param.sched_priority = (min + max) / 2;
pthread_attr_setschedparam(&attr, &param);

3.3 Scheduling Policies

Pthread supports three policies: SCHED_OTHER (default time‑sharing), SCHED_FIFO (real‑time first‑in‑first‑out), and SCHED_RR (real‑time round‑robin). The policy is set via pthread_attr_setschedpolicy .

pthread_attr_t attr;
pthread_attr_init(&attr);
pthread_attr_setschedpolicy(&attr, SCHED_RR);

4. Advantages and Disadvantages of Pthread

4.1 Advantages

Cross‑platform portability, tight integration with C/C++, low‑level control over thread resources, and widespread support on modern Unix‑like systems.

4.2 Disadvantages

Lack of built‑in read‑write locks, a relatively small API surface compared to higher‑level threading libraries, and the need for extra code to implement some advanced features.

5. Application Scenarios

5.1 Mutex Protection Example

Simulating multiple ticket‑selling windows, a mutex ensures that ticket count updates are atomic.

#include
#include
#include
int tickets = 100;
pthread_mutex_t mutex;

void* sellTickets(void* arg){
    while(tickets > 0){
        pthread_mutex_lock(&mutex);
        if(tickets > 0){
            printf("Window %ld sold a ticket, remaining %d\n", pthread_self(), --tickets);
        }
        pthread_mutex_unlock(&mutex);
    }
    return NULL;
}

int main(){
    pthread_mutex_init(&mutex, NULL);
    pthread_t threads[5];
    for(int i=0;i<5;i++) pthread_create(&threads[i], NULL, sellTickets, NULL);
    for(int i=0;i<5;i++) pthread_join(threads[i], NULL);
    pthread_mutex_destroy(&mutex);
    return 0;
}

5.2 Barrier Synchronization Example

Using pthread_barrier to synchronize three worker threads after they finish processing their data.

#include
#include
#include
pthread_barrier_t barrier;

void* processData(void* arg){
    int id = *(int*)arg;
    printf("Thread %d processing...\n", id);
    sleep(id + 1);
    printf("Thread %d finished, waiting...\n", id);
    pthread_barrier_wait(&barrier);
    if(id == 0) printf("All threads finished, starting aggregation...\n");
    return NULL;
}

int main(){
    pthread_t threads[3];
    int ids[3] = {0,1,2};
    pthread_barrier_init(&barrier, NULL, 3);
    for(int i=0;i<3;i++) pthread_create(&threads[i], NULL, processData, &ids[i]);
    for(int i=0;i<3;i++) pthread_join(threads[i], NULL);
    pthread_barrier_destroy(&barrier);
    return 0;
}

5.3 Cross‑Platform Network Server Example

A simple server that accepts client connections and spawns a new thread for each client, compiling on both Linux (using -pthread ) and Windows (using pthreads‑win32 ).

#include
#include
#include
#include
#include
#ifdef _WIN32
#include
#else
#include
#include
#endif

void* handleClient(void* arg){
    // client handling code
    return NULL;
}

int main(){
    int serverSocket;
    struct sockaddr_in serverAddress, clientAddress;
    socklen_t clientAddressLength;
    pthread_t thread;

#ifdef _WIN32
    WSADATA wsaData;
    if (WSAStartup(MAKEWORD(2,2), &wsaData) != 0){
        perror("WSAStartup failed");
        return -1;
    }
#endif

    serverSocket = socket(AF_INET, SOCK_STREAM, 0);
    if (serverSocket == -1){ perror("socket creation failed"); return -1; }
    serverAddress.sin_family = AF_INET;
    serverAddress.sin_addr.s_addr = INADDR_ANY;
    serverAddress.sin_port = htons(8080);
    if (bind(serverSocket, (struct sockaddr*)&serverAddress, sizeof(serverAddress)) == -1){ perror("bind failed"); return -1; }
    if (listen(serverSocket, 5) == -1){ perror("listen failed"); return -1; }
    while(1){
        clientAddressLength = sizeof(clientAddress);
        int clientSocket = accept(serverSocket, (struct sockaddr*)&clientAddress, &clientAddressLength);
        if (clientSocket == -1){ perror("accept failed"); continue; }
        pthread_create(&thread, NULL, handleClient, (void*)&clientSocket);
    }
#ifdef _WIN32
    WSACleanup();
#endif
    return 0;
}

These examples demonstrate how Pthread can be leveraged on various operating systems to solve concurrency challenges, improve performance, and build scalable applications.

LinuxmultithreadingpthreadC ProgrammingThread SynchronizationPOSIX
Deepin Linux
Written by

Deepin Linux

Research areas: Windows & Linux platforms, C/C++ backend development, embedded systems and Linux kernel, etc.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.