5. Pthread Mutex in Linux

Mutex is used to synchronize the thread.

What would be the final value of globalCount in below program?


#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
void *add1_fun(void* arg);
void *add2_fun(void* arg);
int globalCount = 0;
 
void *add1_fun(void* arg) //thread handler
{
    int t_num = (int)arg;
    int i = 0;
    printf("Thread %d created and running \n", t_num);
    for (i=0; i<50000; i++){
        globalCount++;
        }
    printf("Thread %d finishes the work\n", t_num);
    pthread_exit(NULL);
}
 
void *add2_fun(void* arg) //thread handler
{
    int t_num = (int)arg;
    int i = 0;
    printf("Thread %d created and running \n", t_num);
    for (i=0; i<50000; i++){
                globalCount++;
        }
    printf("Thread %d finishes the work\n", t_num);
    pthread_exit(NULL);
}
 
int main(int argc, char *argv[])
{
    pthread_t mythread1;
        pthread_t mythread2;
    pthread_attr_t myattr;
        void *joinResult;
    int x = 0;
    int t_arg = 1;
       
    pthread_attr_init(&myattr);
    pthread_attr_setdetachstate(&myattr, PTHREAD_CREATE_JOINABLE);                 
    if((pthread_create(&mythread1, &myattr, add1_fun,  (void*)t_arg) != 0)){
        printf("Error, thread not created properly\n");
        return 1;
    }
        t_arg = 2;
        if((pthread_create(&mythread2, &myattr, add2_fun,  (void*)t_arg) != 0)){
        printf("Error, thread not created properly\n");
        return 1;
    }
    pthread_attr_destroy(&myattr);
        if(pthread_join(mythread1, &joinResult) != 0 ){
        printf("Error pthread join \n");
        return 1;
    }
        printf("Main : Thread1 joined with result of %d\n", (int)joinResult);
        if(pthread_join(mythread2, &joinResult) != 0 ){
        printf("Error pthread join \n");
        return 1;
    }
        printf("Main : Thread2 joined with result of %d\n", (int)joinResult);
    printf("main finishes the work\n");
        
        printf("\nCount at end : %d\n", globalCount);
    pthread_exit(NULL);
}

Thread 1 will increment globalCount for 50000 times and Thread 2 as well. So final value of globalCount would be 100000. But actual output is not 100000.

Each time you execute the program you will get different value.

Because two thread execute concurrently. Consider the situation in which globalCount = 10, suppose in same time each thread increment the globalCount so value will be 11 not 12.

Actual output of above program in my PC is
Thread 1 created and running 
Thread 2 created and running 
Thread 1 finishes the work
Thread 2 finishes the work
Main : Thread1 joined with result of 0
Main : Thread2 joined with result of 0
main finishes the work

Count at end : 60286

Solution for above problem :
When one thread trying to increment the globalCount we need to lock the variable, then after increment unlock the variable.
This can be establish with the help of mutex API which available in pthread library.;

Steps need for mutex lock and unlock:

  • create a mutex variable of type pthread_mutex_t 
  • lock the globalCount with the help of pthread_mutex_lock API
  • unlock the globalCount when finishes the work with the help of pthread_mutex_unlock

PROGRAM : 
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
void *add1_fun(void* arg);
void *add2_fun(void* arg);
int globalCount = 0;
pthread_mutex_t mutex;
 
void *add1_fun(void* arg) //thread handler 1
{
    int t_num = (int)arg;
    int i = 0;
    printf("Thread %d created and running \n", t_num);
    pthread_mutex_lock(&mutex);
    for (i=0; i<50000; i++){
                globalCount++;
        }
    pthread_mutex_unlock (&mutex);
    printf("Thread %d finishes the work\n", t_num);
    pthread_exit(NULL);
}
 
void *add2_fun(void* arg) //thread handler 2
{
    int t_num = (int)arg;
    int i = 0;
    printf("Thread %d created and running \n", t_num);
        pthread_mutex_lock(&mutex);     
    for (i=0; i<50000; i++){
                globalCount++;
        }
        pthread_mutex_unlock(&mutex);
    printf("Thread %d finishes the work\n", t_num);
    pthread_exit(NULL);
}
 
int main(int argc, char *argv[])
{
    pthread_t mythread1;
        pthread_t mythread2;
    pthread_attr_t myattr;
        void *joinResult;
    int x = 0;
    int t_arg = 1;
        
    pthread_attr_init(&myattr);
    pthread_attr_setdetachstate(&myattr, PTHREAD_CREATE_JOINABLE);                          pthread_mutex_init(&mutex, NULL);
    if((pthread_create(&mythread1, &myattr, add1_fun,  (void*)t_arg) != 0)){
        printf("Error, thread not created properly\n");
        return 1;
    }
        t_arg = 2;
        if((pthread_create(&mythread2, &myattr, add2_fun,  (void*)t_arg) != 0)){
        printf("Error, thread not created properly\n");
        return 1;
    }
   
    pthread_attr_destroy(&myattr);
        if(pthread_join(mythread1, &joinResult) != 0 ){
        printf("Error pthread join \n");
        return 1;
    }
        printf("Main : Thread1 joined with result of %d\n", (int)joinResult);
        if(pthread_join(mythread2, &joinResult) != 0 ){
        printf("Error pthread join \n");
        return 1;
    }
        printf("Main : Thread2 joined with result of %d\n", (int)joinResult);
    printf("main finishes the work\n");
        
        printf("\nCount at end : %d\n", globalCount);
    pthread_exit(NULL);
}
OUTPUT : 
Thread 1 created and running 
Thread 2 created and running 
Thread 1 finishes the work
Main : Thread1 joined with result of 0
Thread 2 finishes the work
Main : Thread2 joined with result of 0
main finishes the work

Count at end : 100000


No comments:

Post a Comment