Reputation: 1071
I've been learning about Multithreaded applications and in particular, about how a mutex can be used to prevent race conditions. However, while writing some code, I discovered a race condition (using the helgrind
tool from valgrind
) in my code, I believe that execution in one thread may be pausing after the unlock and before the return.
If we take the example code below, is a race condition possible in between the mutex unlock and the return statement? If so, how do we get around this problem? (short of requiring the caller to pass in some sort of buffer and returning a constant value like 0
)
#include <pthread.h>
int x = 0;
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
doSomething()
{
pthread_mutex_lock(&mutex);
++x;
pthread_mutex_unlock(&mutex);
/* <-- Race Condition? */
return x;
}
void *t2()
{
doSomething();
}
main()
{
pthread_t thread;
pthread_t_create(&thread, NULL);
doSomething();
pthread_join(thread, NULL);
return 0;
}
NOTE: I understand that in the above example, returning 'x' is useless, as x is global. However, in a library where 'x' needs to be global for library functions, but can't be exposed to the user, the return value becomes important.
Upvotes: 4
Views: 1598
Reputation: 280291
Here's the sequence of events in your current code:
x
variable.The read of x
is completely unprotected.
What you need to do is
x
variable.so that the read is protected by the lock. To do that, store the value of x
to an unshared (local) variable before unlocking the lock, and use that as the return value:
int retval = x;
pthread_mutex_unlock(&mutex);
return retval;
Upvotes: 11