Fundamentals 17 min read

Master Linux Thread Programming: From Basics to Advanced Control

This article provides a comprehensive guide to Linux threads, covering fundamental concepts, the distinction between processes and threads, user‑level vs kernel‑level threading, thread creation and termination with POSIX APIs, attribute settings, cancellation, cleanup, detachment, scheduling policies, and practical code examples.

Liangxu Linux
Liangxu Linux
Liangxu Linux
Master Linux Thread Programming: From Basics to Advanced Control

Basic Concepts of Threads

A thread is the smallest unit of execution that the operating system can schedule. Threads share the address space of their parent process, have separate stacks and program counters, and are lighter than processes.

Differences Between Threads and Processes

Definition: A process has its own memory space; a thread is an execution flow within a process.

Resource Overhead: Processes incur larger creation and destruction costs; threads are cheaper.

Communication: Inter‑process communication (IPC) is complex; threads communicate by directly sharing memory.

Context Switch: Process switches have higher overhead; thread switches are lighter.

Independence: Processes are isolated; threads depend on their parent process and can affect each other.

Advantages of Threads

Responsiveness: While one thread waits for I/O, another can continue processing.

Resource Sharing: Threads share the process’s memory, making data exchange easy.

Efficiency: Creation and destruction overhead is lower than for processes.

Multi‑core Utilization: Threads can run on multiple CPU cores simultaneously.

Disadvantages of Threads

Synchronization Issues: Shared resources can lead to race conditions.

Debugging Difficulty: Non‑deterministic execution order makes debugging harder.

Resource Contention: Competing for the same resources may degrade performance.

Linux Thread Model

User‑Level vs Kernel‑Level Threads

User‑Level Threads: Managed by a user‑space library (e.g., POSIX threads); the kernel is unaware of them. Low switching cost but cannot exploit multiple cores.

Kernel‑Level Threads: Managed by the kernel; each thread appears as a lightweight process (LWP). Can use multiple cores but have higher switching overhead.

Implementation in Linux

Linux implements threads as lightweight processes (LWP). Each thread corresponds to an LWP that shares the same address space. The NPTL library provides POSIX thread support, wrapping LWPs to present a thread abstraction.

Thread Control

Creating Threads

Thread creation is performed via the POSIX thread library ( pthread). The function pthread_create creates a new thread.

#include <pthread.h>
int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
    void *(*start_routine)(void *), void *arg);

Parameters: thread: pointer to a pthread_t that receives the thread identifier. attr: thread attributes (pass NULL for defaults). start_routine: function executed by the new thread. arg: argument passed to start_routine.

Simple creation example:

#include <stdio.h>
#include <pthread.h>
#include <unistd.h>

void* thread_function(void* arg) {
    printf("Thread is running...
");
    sleep(2);
    printf("Thread is exiting...
");
    return NULL;
}

int main() {
    pthread_t thread_id;
    int ret = pthread_create(&thread_id, NULL, thread_function, NULL);
    if (ret != 0) {
        printf("Thread creation failed!
");
        return 1;
    }
    printf("Main thread is running...
");
    pthread_join(thread_id, NULL);
    printf("Main thread is exiting...
");
    return 0;
}

The main thread creates a child thread, the child runs thread_function, and the main thread waits with pthread_join.

Terminating Threads

Threads can end by:

Normal Return: The thread function finishes and returns.

pthread_exit : Explicitly terminates the calling thread.

pthread_cancel : Another thread requests cancellation; the target stops at the next cancellation point (e.g., sleep, read, write).

Cancellation example:

#include <stdio.h>
#include <pthread.h>
#include <unistd.h>

void* thread_function(void* arg) {
    printf("Thread is running...
");
    while (1) {
        printf("Thread is working...
");
        sleep(1);
    }
    return NULL;
}

int main() {
    pthread_t thread_id;
    int ret = pthread_create(&thread_id, NULL, thread_function, NULL);
    if (ret != 0) {
        printf("Thread creation failed!
");
        return 1;
    }
    sleep(3); // let the thread run
    pthread_cancel(thread_id);
    printf("Thread has been canceled.
");
    pthread_join(thread_id, NULL);
    printf("Main thread is exiting...
");
    return 0;
}

Thread Attributes

Attributes are set via pthread_attr_t. Common attributes include detach state, stack size, and scheduling policy.

Detach State: Joinable (requires pthread_join) or detached (resources released automatically).

Stack Size: Customizable stack memory for the thread.

Scheduling Policy: FIFO, round‑robin, or default.

Example of creating a detached thread:

#include <stdio.h>
#include <pthread.h>
#include <unistd.h>

void* thread_function(void* arg) {
    printf("Thread is running...
");
    sleep(2);
    printf("Thread is exiting...
");
    return NULL;
}

int main() {
    pthread_t thread_id;
    int ret = pthread_create(&thread_id, NULL, thread_function, NULL);
    if (ret != 0) {
        printf("Thread creation failed!
");
        return 1;
    }
    pthread_detach(thread_id); // make thread detached
    printf("Main thread is running...
");
    sleep(3);
    printf("Main thread is exiting...
");
    return 0;
}

Thread Cancellation

Cancellation is performed with pthread_cancel. The target thread stops at the next cancellation point such as sleep, read, or write.

Thread Cleanup

When a thread terminates, cleanup handlers registered with pthread_cleanup_push and pthread_cleanup_pop are executed to release resources.

#include <stdio.h>
#include <pthread.h>
#include <unistd.h>

void cleanup_function(void* arg) {
    printf("Cleanup function is called: %s
", (char*)arg);
}

void* thread_function(void* arg) {
    pthread_cleanup_push(cleanup_function, "Resource 1");
    pthread_cleanup_push(cleanup_function, "Resource 2");
    printf("Thread is running...
");
    sleep(2);
    printf("Thread is exiting...
");
    pthread_cleanup_pop(1);
    pthread_cleanup_pop(1);
    return NULL;
}

int main() {
    pthread_t thread_id;
    int ret = pthread_create(&thread_id, NULL, thread_function, NULL);
    if (ret != 0) {
        printf("Thread creation failed!
");
        return 1;
    }
    pthread_join(thread_id, NULL);
    printf("Main thread is exiting...
");
    return 0;
}

Thread Detachment

Detached threads release their resources automatically after termination, eliminating the need for pthread_join. Use pthread_detach or set the detach state attribute before creation.

Considerations

Resources are freed automatically; no join required.

Return values cannot be retrieved.

Once detached, a thread cannot be joined.

Thread Scheduling

Scheduling Policies

SCHED_FIFO: First‑in‑first‑out; higher‑priority threads run until they yield.

SCHED_RR: Round‑robin with time slices for equal‑priority threads.

SCHED_OTHER: Default time‑sharing policy.

Setting Scheduling Policy

Use pthread_setschedparam or attribute functions to set policy and priority.

#include <stdio.h>
#include <pthread.h>
#include <sched.h>
#include <unistd.h>

void* thread_function(void* arg) {
    printf("Thread is running...
");
    sleep(2);
    printf("Thread is exiting...
");
    return NULL;
}

int main() {
    pthread_t thread_id;
    pthread_attr_t attr;
    struct sched_param param;
    pthread_attr_init(&attr);
    pthread_attr_setschedpolicy(&attr, SCHED_FIFO);
    param.sched_priority = 50;
    pthread_attr_setschedparam(&attr, &param);
    int ret = pthread_create(&thread_id, &attr, thread_function, NULL);
    if (ret != 0) {
        printf("Thread creation failed!
");
        return 1;
    }
    pthread_join(thread_id, NULL);
    printf("Main thread is exiting...
");
    pthread_attr_destroy(&attr);
    return 0;
}

Conclusion

The article covered Linux thread fundamentals, creation, termination, attribute configuration, cancellation, cleanup, detachment, and scheduling. The provided code snippets illustrate how to apply these concepts in real programs and manage concurrency on Linux systems.

Thread concept diagram
Thread concept diagram
Thread vs process comparison
Thread vs process comparison
Thread advantages
Thread advantages
Thread disadvantages
Thread disadvantages
Thread scheduling
Thread scheduling
Thread cleanup
Thread cleanup
Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

LinuxpthreadThreadsPOSIX
Liangxu Linux
Written by

Liangxu Linux

Liangxu, a self‑taught IT professional now working as a Linux development engineer at a Fortune 500 multinational, shares extensive Linux knowledge—fundamentals, applications, tools, plus Git, databases, Raspberry Pi, etc. (Reply “Linux” to receive essential resources.)

0 followers
Reader feedback

How this landed with the community

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.