How to Create Threads in Linux (With a C Example Program)

by Himanshu Arora on April 6, 2012

In the part I of the Linux Threads series, we discussed various aspects related to threads in Linux.

In this article we will focus on how a thread is created and identified. We will also present a working C program example that will explain how to do basic threaded programming.

Linux Threads Series: part 1, part 2 (this article), part 3.

Thread Identification

Just as a process is identified through a process ID, a thread is identified by a thread ID. But interestingly, the similarity between the two ends here.

  • A process ID is unique across the system where as a thread ID is unique only in context of a single process.
  • A process ID is an integer value but the thread ID is not necessarily an integer value. It could well be a structure
  • A process ID can be printed very easily while a thread ID is not easy to print.

The above points give an idea about the difference between a process ID and thread ID.

Thread ID is represented by the type ‘pthread_t’.  As we already discussed that in most of the cases this type is a structure, so there has to be a function that can compare two thread IDs.

#include <pthread.h>
int pthread_equal(pthread_t tid1, pthread_t tid2);

So as you can see that the above function takes two thread IDs and returns nonzero value if both the thread IDs are equal or else it returns zero.

Another case may arise when a thread would want to know its own thread ID. For this case the following function provides the desired service.

#include <pthread.h>
pthread_t pthread_self(void);

So we see that the function ‘pthread_self()’ is used by a thread for printing its own thread ID.

Now, one would ask about the case where the above two function would be required. Suppose there is a case where a link list contains data for different threads. Every node in the list contains a thread ID and the corresponding data. Now whenever a thread tries to fetch its data from linked list, it first gets its own ID by calling ‘pthread_self()’ and then it calls the ‘pthread_equal()’ on every node to see if the node contains data for it or not.

An example of the generic case discussed above would be the one in which a master thread gets the jobs to be processed and then it pushes them into a link list. Now individual worker threads parse the linked list and extract the job assigned to them.

Thread Creation

Normally when a program starts up and becomes a process, it starts with a default thread. So we can say that every process has at least one thread of control.  A process can create extra threads using the following function :

#include <pthread.h>
int pthread_create(pthread_t *restrict tidp, const pthread_attr_t *restrict attr, void *(*start_rtn)(void), void *restrict arg)

The above function requires four arguments, lets first discuss a bit on them :

  • The first argument is a pthread_t type address. Once the function is called successfully, the variable whose address is passed as first argument will hold the thread ID of the newly created thread.
  • The second argument may contain certain attributes which we want the new thread to contain.  It could be priority etc.
  • The third argument is a function pointer. This is something to keep in mind that each thread starts with a function and that functions address is passed here as the third argument so that the kernel knows which function to start the thread from.
  • As the function (whose address is passed in the third argument above) may accept some arguments also so we can pass these arguments in form of a pointer to a void type. Now, why a void type was chosen? This was because if a function accepts more than one argument then this pointer could be a pointer to a structure that may contain these arguments.

A Practical Thread Example

Following is the example code where we tried to use all the three functions discussed above.

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

pthread_t tid[2];

void* doSomeThing(void *arg)
{
    unsigned long i = 0;
    pthread_t id = pthread_self();

    if(pthread_equal(id,tid[0]))
    {
        printf("\n First thread processing\n");
    }
    else
    {
        printf("\n Second thread processing\n");
    }

    for(i=0; i<(0xFFFFFFFF);i++);

    return NULL;
}

int main(void)
{
    int i = 0;
    int err;

    while(i < 2)
    {
        err = pthread_create(&(tid[i]), NULL, &doSomeThing, NULL);
        if (err != 0)
            printf("\ncan't create thread :[%s]", strerror(err));
        else
            printf("\n Thread created successfully\n");

        i++;
    }

    sleep(5);
    return 0;
}

So what this code does is :

  • It uses the pthread_create() function to create two threads
  • The starting function for both the threads is kept same.
  • Inside the function ‘doSomeThing()’, the thread uses pthread_self() and pthread_equal() functions to identify whether the executing thread is the first one or the second one as created.
  • Also, Inside the same function ‘doSomeThing()’ a for loop is run so as to simulate some time consuming work.

Now, when the above code is run, following was the output :

$ ./threads
Thread created successfully
First thread processing
Thread created successfully
Second thread processing

As seen in the output, first thread is created and it starts processing, then the second thread is created and then it starts processing. Well one point to be noted here is that the order of execution of threads is not always fixed. It depends on the OS scheduling algorithm.

Note: The whole explanation in this article is done on Posix threads. As can be comprehended from the type, the pthread_t type stands for POSIX threads. If an application wants to test whether POSIX threads are supported or not, then the application can use the macro _POSIX_THREADS for compile time test. To compile a code containing calls to posix APIs, please use the compile option ‘-pthread’.


Linux Sysadmin Course Linux provides several powerful administrative tools and utilities which will help you to manage your systems effectively. If you don’t know what these tools are and how to use them, you could be spending lot of time trying to perform even the basic administrative tasks. The focus of this course is to help you understand system administration tools, which will help you to become an effective Linux system administrator.
Get the Linux Sysadmin Course Now!

If you enjoyed this article, you might also like..

  1. 50 Linux Sysadmin Tutorials
  2. 50 Most Frequently Used Linux Commands (With Examples)
  3. Top 25 Best Linux Performance Monitoring and Debugging Tools
  4. Mommy, I found it! – 15 Practical Linux Find Command Examples
  5. Linux 101 Hacks 2nd Edition eBook Linux 101 Hacks Book

Bash 101 Hacks Book Sed and Awk 101 Hacks Book Nagios Core 3 Book Vim 101 Hacks Book

{ 8 comments… read them below or add one }

1 steve April 6, 2012 at 9:46 am

Hello,

Great article but missing a few things.

I noticed you are return NULL from your worker/background thread. Should be pthread_exit(NULL) NULL since you are not returning any arguments. This should clean up a few things before the thread exits.

Also you have a sleep() function at the end of main. I guess if the thread had a long task that takes more than 5 seconds then main would finish and as the main thread created the worker thread that would get killed as well, which could result it UB and cause you program to crash.

You should just pthread_join(thread_id) for main to wait for the worker thread to finish.

Or you can use pthread_exit(NULL) at the end of main. So that the main thread would finish without killing the worker thread. The worker thread would finish without any problem. However, I would recommend pthread_join() so you can exit your program in a controlled way.

Hope this helps,

2 Himanshu April 7, 2012 at 3:34 am

@steve
Hi Steve, thanks for you valuable comments. The two points that you brought into notice will be covered in the next part of the ongoing series of Linux threads. I intentionally did not focus on ‘pthread_exit()’ and the ‘sleep()’ function in this part as this part was intended to just give a small overview of how threads come alive. The subsequent parts will peel of the layers and will focus on deeper aspects including ‘pthread_exit()’ and why sleep() should not be used etc..

3 SF November 5, 2012 at 4:52 am

Also for clarity, it should be added to link against library -lpthread for the example given to build correctly.

4 Chokho November 5, 2012 at 11:48 am

Another Example that might help

#include
#include
#include

void * func(void * param){
printf(“Inside Thread function\n”);
char ** var = (char **)param;
printf(“The passed argument is \”%s\”\n”, *var);
int * i;
i=(int *)malloc(4);
*i=100;
pthread_exit((void*)i);
}

int main(int argc, char * argv[]){ //Argument to be passed as command line argument
int * retval;
retval = (int *)malloc(4);
pthread_t tid;
pthread_attr_t attr;
pthread_attr_init(&attr);
pthread_create(&tid,&attr,func,&argv[1]);
pthread_join(tid, (void **)&retval);
printf(“retval is %d\n”, *retval);
}

5 Dominic Pritham July 22, 2013 at 6:46 pm

Hi, you mentioned that thread ID can be a structure. And you also mentioned that thread IDs can be compared. In C, can structures be compared? Isn’t it a syntax error if you try to compare two structures?

Thank you,
Dominic Pritham

6 tweety October 14, 2013 at 11:00 am

can u tell me when will dosomething function be invocked??

7 saikumar November 23, 2014 at 11:05 pm

hello sir,
i have a doubt in my program
HOW TO KILL REMAINING THREADS WHEN WE COME OUT OF ANY SINGLE THREAD ?
I searched for this but no result! i think u have great knowledge in this area could u help me to solve this

8 Sam November 26, 2014 at 5:20 pm

simple, clear, and helpful. thanks dude.

Leave a Comment

Previous post:

Next post: