Un programme utilisant Semaphores fonctionne correctement sous Linux… des résultats inattendus sous Mac osX

J’ai écrit un programme simple qui résout le problème Lecteurs-Enregistreurs en utilisant des sémaphores. Il fonctionne parfaitement sous Linux, mais lorsque je l’exécute sur mon Mac OSX, j’obtiens des résultats inattendus et je ne comprends pas pourquoi.

Mon programme:

#include  #include  #include  #include  #include  void* function1(void* val); void* function2(void* val); // shared values volatile int X; volatile int Y; // declare semaphores sem_t s1; sem_t s2; main() { void* status; pthread_t thread1; pthread_t thread2; srand(time(NULL)); // initialize semaphores to zero sem_init(&s1, 0, 0); sem_init(&s2, 0, 0); pthread_create(&thread1, NULL, function1, NULL); pthread_create(&thread2, NULL, function2, NULL); pthread_join(thread1, &status); pthread_join(thread2, &status); sem_destroy(&s1); sem_destroy(&s2); } void* function1(void* val) { while(1) { X = rand()%1000; // write printf("After thread ID A writes to X, X = %d\n", X); sem_post(&s1); // signal sem_wait(&s2); // wait printf("After thread ID A reads from Y, Y = %d\n", Y); // read sleep(3); } } void* function2(void* val) { while(1) { sem_wait(&s1); // wait printf("After thread ID B reads from X, X = %d\n", X); // read Y = rand()%1000; // write printf("After thread ID B write to Y, Y = %d\n", Y); sem_post(&s2); // signal sleep(3); } } 

La sortie que je reçois sur Linux (à quoi elle est censée ressembler):

 After thread ID A writes to X, X = 100 After thread ID B reads from X, X = 100 After thread ID B write to Y, Y = 234 After thread ID A reads from Y, Y = 234 ... 

La sortie sur Mac osX (inattendu):

 After thread ID A writes to X, X = 253 After thread ID A reads from Y, Y = 0 After thread ID B reads from X, X = 253 After thread ID B write to Y, Y = 728 ... 

Vérifiez le retour d’erreur sur les appels sem_init; Je parie que la version OS X renvoie une erreur “Fonction non implémentée”.

En effet, les sémaphores POSIX non nommés ne sont pas implémentés sous OS X. Vous devez utiliser des sémaphores nommés ou des variables pthread mutex / condition.

Juste pour compléter, voici une version fonctionnelle de Mac OS X qui utilise sem_open() et sem_unlink() au lieu de sem_init() et sem_destroy() .

 /* cat semtest.c source: "Program using Semaphores runs fine on Linux...unexpected results on Mac osX", http://stackoverflow.com/questions/4136181/program-using-semaphores-runs-fine-on-linux-unexpected-results-on-mac-osx comstackd on Mac OS X 10.6.8 with: gcc -ansi -pedantic -std=gnu99 -Os -Wall -Wextra -Wshadow -l pthread -o semtest semtest.c ./semtest */ #include  #include  #include  #include  #include  #include  void* function1(); void* function2(); // shared values volatile int X; volatile int Y; // declare semaphores //sem_t s1; //sem_t s2; sem_t *s1; sem_t *s2; static const char *semname1 = "Semaphore1"; static const char *semname2 = "Semaphore2"; int main(void) { void* status; pthread_t thread1; pthread_t thread2; srand(time(NULL)); /* // initialize semaphores to zero sem_init(&s1, 0, 0); sem_init(&s2, 0, 0); */ s1 = sem_open(semname1, O_CREAT, 0777, 0); if (s1 == SEM_FAILED) { fprintf(stderr, "%s\n", "ERROR creating semaphore semname1"); exit(EXIT_FAILURE); } s2 = sem_open(semname2, O_CREAT, 0777, 0); if (s2 == SEM_FAILED) { fprintf(stderr, "%s\n", "ERROR creating semaphore semname2"); exit(EXIT_FAILURE); } pthread_create(&thread1, NULL, function1, NULL); pthread_create(&thread2, NULL, function2, NULL); pthread_join(thread1, &status); pthread_join(thread2, &status); //sem_destroy(&s1); //sem_destroy(&s2); sem_unlink(semname1); sem_unlink(semname2); return 0; } void* function1() { while(1) { X = rand()%1000; // write printf("After thread ID A writes to X, X = %d\n", X); //sem_post(&s1); // signal //sem_wait(&s2); // wait sem_post(s1); // signal sem_wait(s2); // wait printf("After thread ID A reads from Y, Y = %d\n", Y); // read sleep(3); } } void* function2() { while(1) { //sem_wait(&s1); // wait sem_wait(s1); // wait printf("After thread ID B reads from X, X = %d\n", X); // read Y = rand()%1000; // write printf("After thread ID B write to Y, Y = %d\n", Y); //sem_post(&s2); // signal sem_post(s2); // signal sleep(3); } }