pthreads

Race condition in pthreads

Introduction#

When writing multi-threaded applications, one of the most common problems experienced are race conditions. So we document the How do you detect them? and How do you handle them?

Example: Consider will have two threads T1 and T2.

How do you detect them?

If the same variable/resource/memory location is accessible by multiple threads and at least of the thread is changing the value of variable/resource/memory location, then Race Condition can occurred. Because if a thread is changing the value of variable/resource/memory location and another thread tries to read the same then it will not get the updated value.

Note: If all threads are just reading the variable/resource/memory location then Race Condition will not occur.

Example: Program suffers from Race Condition

#include <stdio.h>
#include <pthread.h>

int x= 0;

void* fun(void* in)
{
    int i;
    for ( i = 0; i < 10000000; i++ )
    {
        x++;
    }
}

int main()
{
    pthread_t t1, t2;
    printf("Point 1 >> X is: %d\n", x);

    pthread_create(&t1, NULL, fun, NULL);
    pthread_create(&t2, NULL, fun, NULL);
    pthread_join(t1, NULL);
    pthread_join(t2, NULL);

    printf("Point 2 >> X is: %d\n", x);
    return 0;
}

The output on my screen is:

Point 1 >> X is: 0
Point 2 >> X is: 9925047

Your output will vary. But for sure it will not be 20,000,000. Since both Thread executing the same loop and having global variable int x;

for ( i = 0; i < 10000000; i++ )
{
   x++; 
}

So final value of x in line Point 2 >> X is: 9925047 should be 20,000,000. But it is not so.

The state of x can be changed by another thread during the time between x is being read and when it is written back.

Let’s say a thread retrieves the value of x, but hasn’t stored it yet. Another thread can also retrieve the same value of x (because no thread has changed it yet) and then they would both be storing the same value (x+1) back in x!

Example:

Thread 1: reads x, value is 7

Thread 1: add 1 to x, value is now 8

Thread 2: reads x, value is 7

Thread 1: stores 8 in x

Thread 2: adds 1 to x, value is now 8

Thread 2: stores 8 in x

How do you handle them?

Race conditions can be avoided by employing some sort of locking mechanism before the code that accesses the shared resource or mutual exclusion.

Following is modified program:

Example: Race Condition problem resolved

#include <stdio.h>
#include <pthread.h>

int x= 0;
//Create mutex
pthread_mutex_t test_mutex;

void* fun(void* in)
{
    int i;
    for ( i = 0; i < 10000000; i++ )
    {
        //Lock mutex before going to change variable
        pthread_mutex_lock(&test_mutex);
        x++;
        //Unlock mutex after changing the variable
        pthread_mutex_unlock(&test_mutex);
    }
}

int main()
{
    pthread_t t1, t2;
    printf("Point 1 >> X is: %d\n", x);

    //Initlize mutex
    pthread_mutex_init(&test_mutex, NULL);

    pthread_create(&t1, NULL, fun, NULL);
    pthread_create(&t2, NULL, fun, NULL);
    pthread_join(t1, NULL);
    pthread_join(t2, NULL);

    //Destroy mutex after use
    pthread_mutex_destroy(&test_mutex);
    printf("Point 2 >> X is: %d\n", x);
    return 0;
}

Following is the output:

Point 1 >> X is: 0
Point 2 >> X is: 20000000

Here, the answer comes out as 20,000,000 every time.

Note: Modified program, which is free from race condition error, will take much longe to execute. Because there is overburden on mutex lock and unlock.


This modified text is an extract of the original Stack Overflow Documentation created by the contributors and released under CC BY-SA 3.0 This website is not affiliated with Stack Overflow