Example for using shared data between two threads / How to use pthread_mutex_lock to prevent modification of shared variables

Following is the simple example to show, how we can create two threads at a time and make one thread locked on a mutex, till another thread releases previously acquired mutex so that both the threads doesn’t access / try to modify shared variable simultaneously giving us an unpredected result.

In below program, for demostration, we have created a global variable to which we try to add 5 from one thread and substract 3 from another thread.

#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
 
int global_sum = 0;
 
pthread_t tid1, tid2;
pthread_mutex_t mutex_lock;
 
void *function_shared_between_threads(void *arg) {
    int i;
    int *passed_value = (int*)arg;
 
    printf("called from : %d \n", *passed_value);
    pthread_mutex_lock (&mutex_lock);
    for (i=0; i < 5; i++) {
        printf("adding : %d \n : final sum: %d", *passed_value, global_sum);
        global_sum += *passed_value;
        sleep(1);
    }
    pthread_mutex_unlock (&mutex_lock);
    pthread_exit((void*) 0);
}
 
int main (int argc, char *argv[]) {
    int val1 = 5;
    int val2 = -2;
    void *status;
    printf("Executing main...\n");
    pthread_mutex_init(&mutex_lock, NULL);             
 
    printf("Creating Thread 1...\n");
    pthread_create(&tid1, NULL, &function_shared_between_threads, (void *)&val1);
    printf("Creating Thread 2...\n");
    pthread_create(&tid2, NULL, &function_shared_between_threads, (void *)&val2);
 
    printf("Waiting for Thread 1 to complete...\n");
    pthread_join(tid1, &status);
    printf("Waiting for Thread 2 to complete...\n");
    pthread_join(tid2, &status);
 
    pthread_mutex_destroy(&mutex_lock);
    printf("Final Value : %d\n", global_sum);
    pthread_exit(NULL);
    return 0;
}

Compile the program by linking pthread library as,

 $ gcc -o shared_data_between_threads shared_data_between_threads.c -lpthread 
 $ ./shared_data_between_threads 
Executing main...
Creating Thread 1...
Creating Thread 2...
Waiting for Thread 1 to complete...
called from : -2 
called from : 5 
adding : 5 : final sum: 0
adding : 5 : final sum: 5
adding : 5 : final sum: 10
adding : 5 : final sum: 15
adding : 5 : final sum: 20
adding : -2 : final sum: 25
Waiting for Thread 2 to complete...
adding : -2 : final sum: 23
adding : -2 : final sum: 21
adding : -2 : final sum: 19
adding : -2 : final sum: 17
Final Value : 15

As we see above, if we use proper pthread_lock, although both threads are created at a time, thread which adds 5, continues to operate on global_sum till it completes its 5 iterations and we see 5 getting added uniformly and once first thread releases the lock, second thread which was waiting continues with the operations.

Now, lets try to remove the mutex lock and see, how we get the output.

#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
 
int global_sum = 0;
 
pthread_t tid1, tid2;
 
void *function_shared_between_threads(void *arg) {
    int i;
    int *passed_value = (int*)arg;
 
    printf("called from : %d \n", *passed_value);
    for (i=0; i < 5; i++) {
        printf("adding : %d : final sum: %d\n", *passed_value, global_sum);
        global_sum += *passed_value;
        sleep(1);
    }
    pthread_exit((void*) 0);
}
 
int main (int argc, char *argv[]) {
    int val1 = 5;
    int val2 = -2;
    void *status;
    printf("Executing main...\n");             
 
    printf("Creating Thread 1...\n");
    pthread_create(&tid1, NULL, &function_shared_between_threads, (void *)&val1);
    printf("Creating Thread 2...\n");
    pthread_create(&tid2, NULL, &function_shared_between_threads, (void *)&val2);
 
    printf("Waiting for Thread 1 to complete...\n");
    pthread_join(tid1, &status);
    printf("Waiting for Thread 2 to complete...\n");
    pthread_join(tid2, &status);
 
    printf("Final Value : %d\n", global_sum);
    pthread_exit(NULL);
    return 0;
} 
 $ ./shared_data_between_threads
Executing main...
Creating Thread 1...
Creating Thread 2...
Waiting for Thread 1 to complete...
called from : 5 
adding : 5 : final sum: 0
called from : -2 
adding : -2 : final sum: 5
adding : 5 : final sum: 3
adding : -2 : final sum: 3
adding : 5 : final sum: 6
adding : -2 : final sum: 6
adding : 5 : final sum: 9
adding : -2 : final sum: 14
adding : 5 : final sum: 12
adding : -2 : final sum: 17
Waiting for Thread 2 to complete...
Final Value : 15

As, we can see, if we dont use pthread_mutex_lock both threads tries to access and update global_sum resulting some random behaviour as we see in prints above.

Leave a Comment