I am currently learning C from MIT's Open Courseware course called Practical Programming in C. In discussing race conditions in multithreading, the lecture notes contained an example of a program with a race condition and how it could be resolved using a mutex. The code works as expected on linux systems, but not on OS X.
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
pthread_mutex_t mutex; // Added to fix race condition
unsigned int cnt = 0;
void *count(void *arg) {
int i;
for (i = 0; i < 100000000; i++) {
pthread_mutex_lock(&mutex); // Added to fix race condition
cnt++;
pthread_mutex_unlock(&mutex); // Added to fix race condition
}
return NULL;
}
int main() {
pthread_t tids[4];
int i;
for (i = 0; i < 4; i++)
pthread_create(&tids[i], NULL, count, NULL);
for (i = 0; i < 4; i++)
pthread_join(tids[i], NULL);
pthread_mutex_destroy(&mutex); // Added to fix race condition
printf("cnt = %u\n", cnt);
return 0;
}
Before adding the mutex and the corresponding function calls, the behavior was as expected, producing a variable fraction of the ideally correct response for cnt (400000000), different on each run. After adding the mutex, this was still happening, although there was an obvious increase in the results, suggesting it had some of the expected effect, but far from perfect.
I tried compiling this program on 3 other computers/VMs: one running OS X 10.10 (the first was running 10.11), one with Kali Linux (essentially Debian Jessie under the hood), and one running Ubuntu. Both of the OS X runs showed the same odd behavior as described. However, both Linux systems produced the perfect 400000000 as expected.
So my question is, why doesn't the mutex work as expected on OS X?
You didn't initialize the mutex. You can either do this:
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
or in the main
function, do this:
if ( pthread_mutex_init( &mutex, NULL) != 0 )
printf( "mutex init failed\n" );
The reason why it works with linux is, because under linux :
#define PTHREAD_MUTEX_INITIALIZER { { 0, 0, 0, 0, 0, { 0 } } }
which is exactly how the mutex is initialized anyway, since it is a .bss-variable.
Under MacOSX, it is some other magic value:
#define PTHREAD_MUTEX_INITIALIZER {_PTHREAD_MUTEX_SIG_init, {0}}
#define _PTHREAD_MUTEX_SIG_init 0x32AAABA7
so it indeed has to be initialized to have it working correctly.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With