C - Thread                                        Home : www.sharetechnote.com

 

 

 

 

Thread

 

 

Threading is a mechanism in which you can execute multiple 'jobs(procedures)' simultaneously within the same task.

 

 

 

Fundamental Logic on Threading in C

 

Basic logic (code struture) of threading in C can be summarized as follows.

 

Step 1 : Define a function to be threaded (to be run as threaded)

    This function should be a void pointer type and has single pointer type argument. The argument can be void as well. It mean you can pass only 0 or 1 parameter into the function. If you want to pass multiple parameters to the function, you may pack all of those parameter into a structure and pass the struct (the pointer to the struct) into the function.

 

Step 2 : Create and Run the thread

    Create the thread using the following function. The thread gets started as soon as the thread is created.

     

    pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine) (void *), void *arg);

     

    NOTE : Refer to the Linux man page for the details of this function.

 

 

Step 3 : Join the thread

    If you just start the thread, the program would exit without waiting until the routine within the thread complete. To force the program wait until the routine within the thread gets completed, execute the following function. I don't understand why it is named as _join(), not something like _wait().

     

    pthread_join(pthread_t thread, void **retval);

     

    NOTE : Refer to the Linux man page for the details of this function.

     

 

 

 

How to Create and Run a Thread ?

 

 

#include <stdio.h>

#include <stdlib.h>

#include <pthread.h>

#include <unistd.h>

 

 

void *SampleThread(void *vargp)

{

    int i = 0;

    

    printf("SampleThread is running ... \n");

    for(i = 0; i < 15; i++) {

        sleep(1);

        printf("timer running inside thread = %d\n", i);

    }

    printf("SampleThread is exiting ... \n");

    return NULL;

}

  

int main()

{

    int i = 0;

    

    pthread_t tid;

    pthread_create(&tid, NULL, SampleThread, NULL);

    

    for(i = 0; i < 5; i++) {

        sleep(2);

        printf("timer running outside thread = %d\n", i);

    }

    

    // this is to make it sure that the program (Application) waiting until the tid thread

    // completes. without this routine, the application move to the next step right away

    // exit(0) in this example.

    pthread_join(tid, NULL);

    

    exit(0);

}

 

Result :-----------------------------------------------

// What I am trying to show you is that printf() outside of thread is running even while printf() within the thread is running. The part in red is from inside of Thread and the part in black is from outside of Thread. This example shows that the program does not immediately goes to the end (exit(0)) even when the main routine (for loop in this example) is complete. The program exits (wait until) when all the routine within the thread gets completed.

 

SampleThread is running ...

timer running inside thread = 0

timer running outside thread = 0

timer running inside thread = 1

timer running inside thread = 2

timer running outside thread = 1

timer running inside thread = 3

timer running inside thread = 4

timer running outside thread = 2

timer running inside thread = 5

timer running inside thread = 6

timer running outside thread = 3

timer running inside thread = 7

timer running inside thread = 8

timer running outside thread = 4 <== main routine (for() loop in this example) completes here

timer running inside thread = 9  <== SampleThread() continues to run

timer running inside thread = 10

timer running inside thread = 11

timer running inside thread = 12

timer running inside thread = 13

timer running inside thread = 14

SampleThread is exiting ...       <== SampleThread() finishes

<== Program ends here

 

 

 

Running Two Threads

 

 

In this example, three different routines are running simultaneously : Two threads and one for() loop in main routine. The program is written in such a way that these three routines needs different length of time to complete. The main purpose of these to show when each of these thread exits and when the whole program finishes.

 

 

#include <stdio.h>

#include <stdlib.h>

#include <pthread.h>

#include <unistd.h>

 

// this is the function to be run as the first thread. It will needs about 10 seconds to complete.

void *SampleThread1(void *vargp)

{

    int i = 0;

    

    printf("SampleThread(1) is running ... \n");

    for(i = 0; i < 10; i++) {

        sleep(1);

        printf("timer running inside SampleThread(1) = %d\n", i);

    }

    printf("SampleThread(1) is exiting ... \n");

    return NULL;

};

 

 

// this is the function to be run as the second thread. It will needs about 15 seconds to complete.

void *SampleThread2(void *vargp)

{

    int i = 0;

    

    printf("SampleThread(2) is running ... \n");

    for(i = 0; i < 15; i++) {

        sleep(1);

        printf("timer running inside SampleThread(2) = %d\n", i);

    }

    printf("SampleThread(2) is exiting ... \n");

    return NULL;

};

 

  

int main()

{

    int i = 0;

    

    pthread_t tid1, tid2;

    pthread_create(&tid1, NULL, SampleThread1, NULL);

    pthread_create(&tid2, NULL, SampleThread2, NULL);

    

        // this is the routine in main, which will run in parallel with the two threads.  It will needs about 14 seconds

      // to complete.

    for(i = 0; i < 7; i++) {

        sleep(2);

        printf("timer running outside thread = %d\n", i);

    }

    printf("timer outside Thread is ended ..\n");

    

    pthread_join(tid1, NULL);

    pthread_join(tid2, NULL);

    

    exit(0);

}

 

 

Result :-----------------------------------------------

// Red part is the print from SampleThread1, Blue part is the print from SampleThread2 and the black is the pring from

// main(). Check in which order each of the routine finishes.

 

SampleThread(1) is running ...

SampleThread(2) is running ...

timer running inside SampleThread(1) = 0

timer running inside SampleThread(2) = 0

timer running outside thread = 0

timer running inside SampleThread(2) = 1

timer running inside SampleThread(1) = 1

timer running inside SampleThread(2) = 2

timer running inside SampleThread(1) = 2

timer running outside thread = 1

timer running inside SampleThread(2) = 3

timer running inside SampleThread(1) = 3

timer running inside SampleThread(2) = 4

timer running inside SampleThread(1) = 4

timer running outside thread = 2

timer running inside SampleThread(2) = 5

timer running inside SampleThread(1) = 5

timer running inside SampleThread(2) = 6

timer running inside SampleThread(1) = 6

timer running outside thread = 3

timer running inside SampleThread(2) = 7

timer running inside SampleThread(1) = 7

timer running inside SampleThread(2) = 8

timer running inside SampleThread(1) = 8

timer running outside thread = 4

timer running inside SampleThread(2) = 9

timer running inside SampleThread(1) = 9

SampleThread(1) is exiting ...

timer running inside SampleThread(2) = 10

timer running outside thread = 5

timer running inside SampleThread(2) = 11

timer running inside SampleThread(2) = 12

timer running outside thread = 6

timer outside Thread is ended ..

timer running inside SampleThread(2) = 13

timer running inside SampleThread(2) = 14

SampleThread(2) is exiting ...

 

 

 

Thread for User Interaction

 

 

#include <stdio.h>

#include <stdlib.h>

#include <pthread.h>

#include <unistd.h>

 

 

void *ThreadSum(void *vargp)

{

 

    long i = 0;

    long long s = 0;

 

    printf("ThreadSum is running ... \n");

 

    while(1) {

        s++;

        if( (s%1000000000) == 0 ) {

            printf("s = %ld\n", s);

            s = 0;

         }

    }

 

    printf("ThreadSum is exiting ... \n");

 

    return NULL;

 

}

 

void *ThreadMult(void *vargp)

{

 

    long i = 0;

    float m = 1;

 

    printf("ThreadMult is running ... \n");

 

    while(1) {

        m *= 1.0000001;

        if( m >= 1000000000 ) {

            printf("m = %f\n", m);

            m = 1;

         }

    }

 

    printf("ThreadMult is exiting ... \n");

 

    return NULL;

 

}

 

 

void *ThreadKey(void *vargp)

{

 

    char c;

 

    printf("ThreadKeyt is running ... \n");

 

    while(1) {

        c = getch();

        printf("Key entered = %c\n",c);

        if(c == 'q')

           break;

    }

 

    printf("ThreadKey is exiting ... \n");

 

    return NULL;

 

}

 

  

 

int main()

{

 

    int i = 0;

 

    pthread_t tid_sum, tid_mult, tid_key;

 

    pthread_create(&tid_sum, NULL, ThreadSum, NULL);

    pthread_create(&tid_mult, NULL, ThreadMult, NULL);

    pthread_create(&tid_key, NULL, ThreadKey, NULL);

 

    pthread_join(tid_key, NULL);

 

    exit(0);

 

}

 

 

Result :-----------------------------------------------

 

ThreadSum is running ...

ThreadKeyt is running ...

ThreadMult is running ...

m = 1000000000.000000

s = 1000000000

m = 1000000000.000000

s = 1000000000

m = 1000000000.000000

Key entered = a

Key entered = s

Key entered = f

m = 1000000000.000000

s = 1000000000

Key entered = c

Key entered = v

m = 1000000000.000000

Key entered = h

s = 1000000000

m = 1000000000.000000

Key entered = q

ThreadKey is exiting ...