Mutex Program

When two threads concurrently access the shared resource(counter), it will yield to inconsistent data. 
The below program depicts the same.

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

int counter = 0;

void* trythis(void *arg)
{
    unsigned long i = 0;
    int *my_id = (int *)arg;

    counter += 1;
    printf("\n Thread %d Job %d has started\n", *my_id, counter);

    for(i=0; i<(0xFFFFFFFF);i++);
    printf("\n Thread %d Job %d has finished\n", *my_id, counter);

    return NULL;
}

int main(void)
{
    int i = 0;
    pthread_t tid[2] = {0};
    int error;

    while(i < 2) {
        error = pthread_create(&(tid[i]), NULL, &trythis, (void *)&(tid[i]));
        if (error != 0)
            printf("\nThread can't be created : [%s]", strerror(error));
        i++;
    }
    pthread_join(tid[0], NULL);
    pthread_join(tid[1], NULL);

    return 0;
}

Output
Thread 1263310592 Job 1 has started
Thread 1254917888 Job 2 has started
Thread 1263310592 Job 2 has finished
Thread 1254917888 Job 2 has finished 

I just wondered why this should be resolved only by mutex though we have pthread_join() which blocks the calling thread until the thread with an identifier equals to the first argument terminates. So, in the while loop, created one thread and immediately wait for it to complete. 

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

int counter = 0;

void* trythis(void *arg)
{
    unsigned long i = 0;
    int *my_id = (int *)arg;

    counter += 1;
    printf("\n Thread %d Job %d has started\n", *my_id, counter);

    for(i=0; i<(0xFFFFFFFF);i++);
    printf("\n Thread %d Job %d has finished\n", *my_id, counter);

    return NULL;
}

int main(void)
{
    int i = 0;
    pthread_t tid[2] = {0};
    int error;

    while(i < 2) {
        error = pthread_create(&(tid[i]), NULL, &trythis, (void *)&(tid[i]));
        if (error != 0)
            printf("\nThread can't be created : [%s]", strerror(error));
        pthread_join(tid[i], NULL);
        i++;
    }

    return 0;
}

Output
Thread -1700481280 Job 1 has started
Thread -1700481280 Job 1 has finished
Thread -1700481280 Job 2 has started
Thread -1700481280 Job 2 has finished 

Then, why do we still go for Mutex?

Obviously, pthread_join is used for thread safety but not safe for shared resource. As thread 2 is created after thread 1, we safely executed thread 1 before thread 2 starts executing. In real case, thread 2 would have already created and will be accessing counter when thread1 also wants to access
the same.

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

int counter = 0;
pthread_mutex_t lock;

void* trythis(void *arg)
{
    unsigned long i = 0;
    int *my_id = (int *)arg;

    pthread_mutex_lock(&lock);

    counter += 1;
    printf("\n Thread %d Job %d has started\n", *my_id, counter);

    for(i=0; i < (0xFFFFFFFF); i++);
    printf("\n Thread %d Job %d has finished\n", *my_id, counter);

    pthread_mutex_unlock(&lock);
    return NULL;
}

int main(void)
{ 
   int i = 0;

    pthread_t tid[2] = {0};
    int error;

    if (pthread_mutex_init(&lock, NULL) != 0) {
        printf("\n mutex init has failed\n");
        return 0;
    }
    while(i < 2) {
        error = pthread_create(&(tid[i]), NULL, &trythis, (void *)&(tid[i]));
        if (error != 0)
            printf("\nThread can't be created : [%s]", strerror(error));
        i++;
    }
    pthread_join(tid[0], NULL);
    pthread_join(tid[1], NULL);
    pthread_mutex_destroy(&lock);
    return 0;
}

Output
Thread 1379645184 Job 1 has started
Thread 1379645184 Job 1 has finished
Thread 1371252480 Job 2 has started
Thread 1371252480 Job 2 has finished


Comments