pthread mutex ne fonctionne pas correctement

J’apprends actuellement le C du cours Open Courseware du MIT appelé “Programmation pratique en C”. Lors de la discussion des conditions de course en multithreading, les notes de cours contenaient un exemple de programme avec une condition de concurrence et la façon de le résoudre à l’aide d’un mutex. Le code fonctionne comme prévu sur les systèmes Linux, mais pas sur OS X.

#include  #include  #include  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; } 

Avant d’append le mutex et les appels de fonction correspondants, le comportement était celui attendu, générant une fraction variable de la réponse idéale pour cnt (400000000), différente à chaque exécution. Après l’ajout du mutex, cela se produisait toujours, même s’il y avait une augmentation évidente des résultats, ce qui donne à penser qu’il a eu l’effet escompté, mais loin d’être parfait.

J’ai essayé de comstackr ce programme sur 3 autres ordinateurs / VM: un sous OS X 10.10 (le premier sous 10.11), un sous Kali Linux (essentiellement Debian Jessie sous le capot) et un sous Ubuntu. Les deux exécutions d’OS X ont montré le même comportement étrange que décrit. Cependant, les deux systèmes Linux ont produit le 400000000 parfait attendu.

Ma question est donc la suivante: pourquoi le mutex ne fonctionne-t-il pas comme prévu sous OS X?

Vous n’avez pas initialisé le mutex. Vous pouvez soit faire ceci:

 pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; 

ou dans la fonction main , procédez comme suit:

 if ( pthread_mutex_init( &mutex, NULL) != 0 ) printf( "mutex init failed\n" ); 

La raison pour laquelle cela fonctionne avec linux est, car sous linux:

 #define PTHREAD_MUTEX_INITIALIZER { { 0, 0, 0, 0, 0, { 0 } } } 

ce qui correspond exactement à l’initialisation du mutex, puisqu’il s’agit d’une variable .bss.

Sous MacOSX, il existe une autre valeur magique:

 #define PTHREAD_MUTEX_INITIALIZER {_PTHREAD_MUTEX_SIG_init, {0}} #define _PTHREAD_MUTEX_SIG_init 0x32AAABA7 

il faut donc bien l’initialiser pour qu’il fonctionne correctement.