2010-11-09 8 views
9

Escribí un programa simple para resolver el problema Lectores-Escritores usando semáforos. Funciona perfectamente en Linux os, pero cuando lo ejecuto en mi Mac OSX obtengo resultados inesperados y no puedo entender por qué.Programa que utiliza semáforos funciona bien en Linux ... resultados inesperados en Mac osX

Mi Programa:

#include <semaphore.h> 
#include <sys/types.h> 
#include <stdio.h> 
#include <pthread.h> 
#include <unistd.h> 

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 salida de recibo en Linux (lo que se supone que debe ser similar):

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 salida de Mac OS X (inesperado):

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 
... 
+2

una solución, pero en cualquier momento un sistema multihilo funciona bien en un lugar (y tienen que trató diferentes tendencias de Linux?), Pero no muy bien en otro lugar entonces estaría sospechando una condición de carrera. –

Respuesta

13

Compruebe el error de retorno en las llamadas sem_init; Apuesto a que encontrará que la versión de OS X muestra un error de "Función no implementada".

Esto es porque unnamed POSIX semaphores are not implemented on OS X. Necesita usar semáforos con nombre o pthread variables mutex/condition.

+1

Muchas gracias. No era consciente de ello. –

2

simplemente para la corrección, aquí es una versión de trabajo Mac OS X utilizando sem_open() y sem_unlink() en lugar de sem_init() y 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 

compiled 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 <semaphore.h> 
#include <sys/types.h> 
#include <stdio.h> 
#include <pthread.h> 
#include <unistd.h> 
#include <stdlib.h> 

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); 
    } 
} 
No
+0

Has salvado mi vida. No realmente, pero básicamente. No pude encontrar nada sobre cómo inicializar semáforos en Mac OS X. No puedo creer que no admitan semáforos sin nombre ... –

Cuestiones relacionadas