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.

SHUFFLED :   Linux commands to find files based on type, size etc.

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.

Android Android Commands Android Java Applications Application Libraries Bash / Shell Scripts Bluetooth driver Build Frameworks Commands and Packages Core Kernel C Programs Development Environment Setup Documents / Books Errors & Failures File Systems Framebuffer / Display Driver git Go Language Programs Hardware Platforms Home Kernel & Device Drivers Kernel Booting and Porting Linux, OS Concepts and Networking Linux Device Drivers Linux Host, Ubuntu, SysAdmin Linux Kernel Linux Networking Middleware Libraries, HAL NDK / Middleware / HAL Network Driver OS Concepts PHP Procfs Filesystem Programming Languages RaspberryPi Scripting and Automation Search Engine Optimisation ( SEO ) Social Media Socurce Code Management ( SCM ) System Administration, Security Testing and Debugging Uncategorized Userspace Utilities Web design and development Wordpress Yocto / Bitbake / Openembedded

Leave a Reply