我正在学习使用C语言的信号量,并遵循以下主题:Producer Consumer program using semaphores and pthreads。
稍作修改(在消费者线程中删除sleep()函数调用),程序将在OSX上的sem_wait()函数之外运行。
但是,当我在其他操作系统上测试相同的程序时,sem_wait()将阻塞该线程。这是我编译和运行的操作系统列表。
我的问题是,为什么这些操作系统之间存在这样的差异?
以下是代码:
#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 ...
Out out on 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 ...
Out on Solaris(使用gcc -pthread -lrt test.c
编译):
[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 ...
答案 0 :(得分: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()&amp; sem_close()代替。请参阅:sem_init on OS X。