Multithreading in C

Last Updated : 6 Jul, 2026

Multithreading is a technique in which a process is divided into multiple threads that execute concurrently. It allows a program to perform multiple tasks simultaneously within a single process, improving performance and responsiveness.

  • Threads are lightweight execution units within a process.
  • Multiple threads share resources while executing independently.

Example: The following program demonstrates the creation and execution of a thread using the POSIX Threads (pthreads) library.

C++
#include <pthread.h>
#include <stdio.h>

void* foo(void* arg)
{
    printf("Thread is running\n");
    return NULL;
}

int main()
{
    pthread_t thread;

    pthread_create(&thread, NULL, foo, NULL);
    pthread_join(thread, NULL);

    return 0;
}

Output
Thread is running

Explanation: The program creates a new thread using pthread_create(). The main thread waits for the created thread to finish using pthread_join().

Threads

A thread represents an independent sequence of execution within a process. Unlike processes, threads share the same memory space and operating system resources.

  • Each thread has its own program counter, registers, and stack.
  • Threads share code, data, files, and signals.
  • Thread creation is faster than process creation.
  • Multiple threads can execute concurrently.
frame_1
Single-Threaded vs Multithreaded Process

Implementing Multithreading Using Pthreads

The POSIX Threads (pthread) library provides APIs for creating, managing, synchronizing, and terminating threads in C. To use pthreads, include the header file:

#include <pthread.h>

If required, compile the program using:

gcc program.c -lpthread

Creating a Thread

The pthread_create() function creates and starts a new thread.

Syntax

pthread_create(thread, attr, routine, arg);

Parameters

  • thread - Stores the ID of the newly created thread.
  • attr - Specifies thread attributes (NULL for default).
  • routine - Function executed by the thread.
  • arg - Argument passed to the thread function.
C
#include <pthread.h>
#include <stdio.h>

void* foo(void* arg) {
    printf("Created a new thread");
    return NULL;
 }
int main() {
    
    // Create a pthread_t variable to store
    // thread ID
    pthread_t thread1;
    
    // Creating a new thread. 
    pthread_create(&thread1, NULL, foo, NULL);
    return 0;
}

Output

 Created a new thread

Explanation: pthread_create() creates a thread that executes the foo() function.

Waiting for a Thread to Finish

The pthread_join() function blocks the calling thread until the specified thread terminates.

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

void* foo(void* arg) {
    printf("Thread is running.\n");
    return NULL;
}

int main() {
    pthread_t thread1;
    pthread_create(&thread1, NULL, foo, NULL);

    // Wait for thread to finish
    pthread_join(thread1, NULL);

    return 0;
}

Output

Thread is running

Explicitly Terminating a Thread

The pthread_exit() function terminates the calling thread explicitly.

Syntax

pthread_exit(value);

C
void* foo(void* arg)
{
    printf("Thread is running.\n");

    pthread_exit(NULL);

    printf("This statement never executes.\n");
}

Output

Thread is running.

Explanation: Once pthread_exit() is called, the thread terminates immediately.

Cancelling a Thread

The pthread_cancel() function is used to request the cancellation of a thread. It sends a cancellation request to the target thread, but the actual termination depends on whether the thread is in a cancellable state and if it handles cancellation. Example:

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

void* myThreadFunc(void* arg) {
    while(1) {
        printf("Thread is running...\n");
        sleep(1);
    }
    return NULL;
}

int main() {
    pthread_t thread;
    pthread_create(&thread, NULL, myThreadFunc, NULL);
    sleep(5);
    //Requesting to cancel the thread after 5 seconds. 
    pthread_cancel(thread);
    // Wait for the thread to terminate
    pthread_join(thread, NULL);  

    printf("Main thread finished.\n");
    return 0;
}

Output

Thread is running...
Thread is running...
Thread is running...
Thread is running...
Thread is running...
Thread is running...
Main thread finished.

Getting the Current Thread ID

pthread_self() function returns the thread ID of the calling thread. This is useful when you need to identify or store the ID of the current thread in multi-threaded programs. Example

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

void* foo(void* arg) {
    
    // Get current thread ID
    pthread_t thisThread = pthread_self();
    printf("Current thread ID: %lu\n",
        (unsigned long)thisThread);
    return NULL;
}

int main() {
    pthread_t thread1;
    pthread_create(&thread1, NULL, foo, NULL);
    pthread_join(thread1, NULL);
    return 0;
}

Output

Current thread ID: 134681321096896

Common Multithreading Issues

Multithreading improves performance but also introduces several challenges.

  • Race Conditions: A race condition occurs when multiple threads access shared data simultaneously, producing unpredictable results.

Example: Two threads updating the same counter variable.

  • Deadlocks: A deadlock occurs when multiple threads wait indefinitely for resources held by each other.

Example: Thread A waits for a resource held by Thread B, while Thread B waits for a resource held by Thread A.

  • Starvation: Starvation occurs when a thread is continuously denied access to resources.

Example: A low-priority thread waiting indefinitely while high-priority threads continue executing.

Thread Synchronization

Thread synchronization ensures safe access to shared resources. Common synchronization mechanisms include:

  • Mutexes - Allow only one thread to access a resource at a time.
  • Semaphores - Control access using counters.
  • Condition Variables - Allow threads to wait for specific conditions.
  • Barriers - Synchronize multiple threads at predefined points.
  • Read-Write Locks - Permit multiple readers and a single writer.

Advantages of Multithreading

Multithreading offers several benefits that improve the efficiency and responsiveness of modern applications:

  • Improves overall application performance and enhances CPU utilization.
  • Provides better responsiveness and improves the user experience.
  • Enables efficient sharing and utilization of system resources.
  • Improves scalability when handling multiple concurrent tasks.

Disadvantages of Multithreading

Despite its advantages, multithreading also introduces several challenges:

  • Increases the complexity of program design and implementation.
  • Requires careful synchronization to manage shared resources safely.
  • Introduces concurrency-related issues such as race conditions and deadlocks.
  • Adds additional overhead for thread creation, scheduling, and management.
Comment