Multithreading in C

We can create multiple threads in our C program to execute multiple tasks in parallel. It helps to utilize the CPU resources efficiently. Even though core C programming does not support multithreading, at least until C11 standard, it has a lot of library support for that purpose.

POSIX thread or pthread is one of the most popular threading libraries in C on Linux.

Time Consuming Tasks

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

void task_1() {
    int i = 0;

    for (i = 0; i < 10; i++) {
        printf("Task 1, iteration: %d.\n", i);
        sleep(1);
    }
}

void task_2() {
    int i = 0;

    for (i = 0; i < 10; i++) {
        printf("Task 2, iteration: %d.\n", i);
        sleep(1);
    }
}

void main()
{
    task_1();
    task_2();
}
$ cc -o test test.c
$ ./test 
Task 1, iteration: 0.
Task 1, iteration: 1.
:
Task 1, iteration: 8.
Task 1, iteration: 9.
Task 2, iteration: 0.
Task 2, iteration: 1.
:
Task 2, iteration: 8.
Task 2, iteration: 9.

We have two time consuming tasks, task_1() and task_2(), in this program. Each function takes 10 seconds to complete execution and prints a message in every one second.

In main(), these two functions are called one after another. From the output, we can see that the first function, task_1(), printed 10 messages and took 10 seconds. The second function, task_2(), could not even get started until task_1() finished. There is no way to execute them in parallel unless we create multiple threads.

Create Multiple Threads to Parallelize Tasks

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

void *task_1(void *param) {
    int i = 0;

    for (i = 0; i < 10; i++) {
        printf("Task 1, iteration: %d.\n", i);
        sleep(1);
    }
}

void *task_2(void *param) {
    int i = 0;

    for (i = 0; i < 10; i++) {
        printf("Task 2, iteration: %d.\n", i);
        sleep(1);
    }
}

void main()
{
    pthread_t thread_id1;
    pthread_t thread_id2;

    /*Create two threads to execute two task in parallel*/
    pthread_create(&thread_id1, NULL, task_1, NULL);
    pthread_create(&thread_id2, NULL, task_2, NULL);

    pthread_join(thread_id1, NULL);
    pthread_join(thread_id2, NULL);
}
$ cc -o test test.c -lpthread
$ ./test 
Task 1, iteration: 0.
Task 2, iteration: 0.
Task 1, iteration: 1.
Task 2, iteration: 1.
Task 2, iteration: 2.
:
:

We changed the program to create two threads for two of our time consuming functions. The pthread library function pthread_create() is used to create a thread.

It takes the function that will be executed in the context of the newly created thread. We passed task_1() in the first call and task_2() in the second call. The function signatures are changed a little bit to be compliant with the requirement of the pthread_create() function.

This function also takes a thread id. We can use this id later to control thread. Like we used it in the next pthread_join() calls.

The pthread_join() function waits until the specified thread completes.

From the output, we can see that the messages from two functions interleaved. That means that both the functions are getting executed in parallel from two different threads.

The pthread_create() functions return immediately after creating the threads. If we don’t call the pthread_join() functions, the main() thread will exit immediately. And you’ll not see any output. You can try that. The pthread_join() calls are also required to cleanup the resources created during thread creating.

Author: Srikanta

I write here to help the readers learn and understand computer programing, algorithms, networking, OS concepts etc. in a simple way. I have 20 years of working experience in computer networking and industrial automation.


If you also want to contribute, click here.

Leave a Reply

Your email address will not be published. Required fields are marked *

0
0
0
0
0
0