2014-02-16 14 views
1

我正在學C語言信號,並遵循以下主題:Producer Consumer program using semaphores and pthreadsOSX/Ubuntu/Soliars上的信號量行爲不同,線程執行超出sem_wait()

通過稍微修改(在消費者線程中刪除sleep()函數調用),該程序將在OSX上超出sem_wait()函數運行。

但是,當我在其他OS上測試相同的程序時,sem_wait()會阻塞該線程。這是我編譯和運行的OS列表。

  • OSX(達爾文內核版本13.0.0 + GCC 4.9 /鐺-500.2.79)< --tried兩者有同樣的問題
  • Ubuntu的(3.8.0-29泛型+ GCC 4.6。 3)
  • 的Solaris(5.10 Generic_147147-26 + GCC 4.2.1)

我的問題是,爲什麼有這些操作系統之間的這種差異?

下面的代碼:

#include <pthread.h> 
#include <stdio.h> 
#include <stdlib.h> 
#include <semaphore.h> //instead of </usr/include/semaphore.h> in the original thread 

// for sleep 
#include <unistd.h> 

#define BUFF_SIZE 5   /* total number of slots */ 
#define NP   3   /* total number of producers */ 
#define NC   3   /* total number of consumers */ 
#define NITERS  4   /* number of items produced/consumed */ 

typedef struct 
{ 
    int buf[BUFF_SIZE]; /* shared var */ 
    int in;    /* buf[in%BUFF_SIZE] is the first empty slot */ 
    int out;    /* buf[out%BUFF_SIZE] is the first full slot */ 
    sem_t full;   /* keep track of the number of full spots */ 
    sem_t empty;   /* keep track of the number of empty spots */ 

    // use correct type here 
    pthread_mutex_t mutex;   /* enforce mutual exclusion to shared data */ 
} sbuf_t; 

sbuf_t shared; 


void *Producer(void *arg) 
{ 
    int i, item, index; 

    index = (int)arg; 


    for (i=0; i < NITERS; i++) 
    { 

     /* Produce item */ 
     item = i; 

     /* Prepare to write item to buf */ 

     /* If there are no empty slots, wait */ 
     sem_wait(&shared.empty); 
     /* If another thread uses the buffer, wait */ 
     pthread_mutex_lock(&shared.mutex); 
     shared.buf[shared.in] = item; 
     shared.in = (shared.in+1)%BUFF_SIZE; 
     printf("[P%d] Producing %d ...\n", index, item); 
     fflush(stdout); 
     /* Release the buffer */ 
     pthread_mutex_unlock(&shared.mutex); 
     /* Increment the number of full slots */ 
     sem_post(&shared.full); 

     /* Interleave producer and consumer execution */ 
     if (i % 2 == 1) sleep(1); 
    } 
    return NULL; 
} 

void *Consumer(void *arg) 
{ 
    int i, item, index; 

    index = (int)arg; 
    for (i=NITERS; i > 0; i--) { 
     sem_wait(&shared.full); 
     pthread_mutex_lock(&shared.mutex); 
     item=i; 
     item=shared.buf[shared.out]; 
     shared.out = (shared.out+1)%BUFF_SIZE; 
     printf("[C%d] Consuming %d ...\n", index, item); 
     fflush(stdout); 
     /* Release the buffer */ 
     pthread_mutex_unlock(&shared.mutex); 
     /* Increment the number of full slots */ 
     sem_post(&shared.empty); 

     /* Interleave producer and consumer execution */ 
     //if (i % 2 == 1) sleep(1); 
     // do not stop, should be blocked by sem_wait() in next run 
    } 
    return NULL; 
} 

int main() 
{ 
    pthread_t idP, idC; 
    int index; 

    sem_init(&shared.full, 0, 0); 
    sem_init(&shared.empty, 0, BUFF_SIZE); 
    pthread_mutex_init(&shared.mutex, NULL); 
    for (index = 0; index < NP; index++) 
    { 
     /* Create a new producer */ 
     pthread_create(&idP, NULL, Producer, (void*)index); 
    } 
    /*create a new Consumer*/ 
    for(index=0; index<NC; index++) 
    { 
     pthread_create(&idC, NULL, Consumer, (void*)index); 
    } 



    pthread_exit(NULL); 
} 

輸出穿上OSX(編譯使用gcc -pthread test.c):

[P0] Producing 0 ... 
[P2] Producing 0 ... 
[P1] Producing 0 ... 
[C0] Consuming 0 ... 
[C1] Consuming 0 ... 
[C2] Consuming 0 ... 
[P0] Producing 1 ... 
[P2] Producing 1 ... 
[P1] Producing 1 ... 
[C0] Consuming 1 ... 
[C1] Consuming 1 ... 
[C2] Consuming 1 ... 
[C0] Consuming 0 ... <-- should be blocked 
[C1] Consuming 0 ... 
[C2] Consuming 1 ... 
[C0] Consuming 1 ... 
[C1] Consuming 1 ... 
[C2] Consuming 0 ... 
[P0] Producing 2 ...  <-- program stopped here for 1s 
[P2] Producing 2 ... 
[P1] Producing 2 ... 
[P0] Producing 3 ... 
[P2] Producing 3 ... 
[P1] Producing 3 ... 

出把在Ubuntu(使用gcc -pthread test.c編譯):

[P2] Producing 0 ... 
[C2] Consuming 0 ... 
[P2] Producing 1 ... 
[C1] Consuming 1 ... 
[P1] Producing 0 ... 
[C0] Consuming 0 ... 
[P1] Producing 1 ... 
[C2] Consuming 1 ... 
[P0] Producing 0 ... 
[C1] Consuming 0 ... 
[P0] Producing 1 ... 
[C0] Consuming 1 ... 
[P2] Producing 2 ...  <-- program stopped here for 1s 
[C2] Consuming 2 ... 
[P1] Producing 2 ... 
[P1] Producing 3 ... 
[C0] Consuming 2 ... 
[C0] Consuming 3 ... 
[P2] Producing 3 ... 
[C2] Consuming 3 ... 
[P0] Producing 2 ... 
[C1] Consuming 2 ... 
[P0] Producing 3 ... 
[C1] Consuming 3 ... 

出來放在Solaris上(使用編譯210):

[P1] Producing 0 ... 
[P2] Producing 0 ... 
[P1] Producing 1 ... 
[C0] Consuming 0 ... 
[C0] Consuming 0 ... 
[C0] Consuming 1 ... 
[P2] Producing 1 ... 
[C1] Consuming 1 ... 
[P0] Producing 0 ... 
[P0] Producing 1 ... 
[C0] Consuming 0 ... 
[C1] Consuming 1 ... 
[P1] Producing 2 ...  <-- program stopped here for 1s 
[P1] Producing 3 ... 
[C2] Consuming 2 ... 
[C1] Consuming 3 ... 
[P2] Producing 2 ... 
[P2] Producing 3 ... 
[C2] Consuming 2 ... 
[C1] Consuming 3 ... 
[P0] Producing 2 ... 
[P0] Producing 3 ... 
[C2] Consuming 2 ... 
[C2] Consuming 3 ... 

回答

1

在OSX上,您的sem_init()返回-1且「Function not implemented」錯誤。所以你的信號燈不工作,你有競爭條件。檢查:

int res = sem_init(&shared.full, 0, 0); 
if (res == -1) { 
    perror("sem_open"); 
    return 1; 
} 

使用sem_open(),sem_unlink()& sem_close()代替。參見:sem_init on OS X