为什么sem_wait不等待mac OSX上的信号量?

时间:2014-11-07 08:31:36

标签: c macos semaphore

以下代码显示了一个生产者 - 消费者示例: 一旦产品生产,消费者将获得该产品。

但我很惊讶消费者会在没有产品的情况下获得产品。

#include <stdlib.h>
#include <pthread.h>
#include <stdio.h>
#include <unistd.h>
#include <semaphore.h>

#define NUM 5
int queue[NUM];
int i;
sem_t *blank_number, *product_number;

void *producer(void *arg) {
    int p = 0;
    while (1) {
        sem_wait(blank_number);
        queue[p] = rand() % 1000 + 1;
        printf("Produce queue[%d]:%d\n", p, queue[p]);
        i = sem_post(product_number);
        //printf("i_p=%d\n", i);
        p = (p+1)%NUM;
        sleep(rand()%5);
    }
}

void *consumer(void *arg) {
    int c = 0;
    while (1) {
        sem_wait(product_number);
        printf("Consume queue[%d]:%d\n", c, queue[c]);
        queue[c] = 0;
        i = sem_post(blank_number);
        //printf("i_c=%d\n", i);
        c = (c+1)%NUM;
        sleep(rand()%5);
    }
}

int main(int argc, char *argv[]) {
    pthread_t pid, cid;  

    //set blank_number to NUM
    blank_number = sem_open("blank_number", O_CREAT, S_IRWXU, NUM);
    if(blank_number == SEM_FAILED){
        perror("open blank_number");
        return 1;
    }
    //set product_number to 0
    product_number = sem_open("product_number", O_CREAT, S_IRWXU, 0);
    if(product_number == SEM_FAILED){
        perror("open product_number");
        return 1;
    }

    pthread_create(&pid, NULL, producer, NULL);
    pthread_create(&cid, NULL, consumer, NULL);
    pthread_join(pid, NULL);
    pthread_join(cid, NULL);
    sem_close(blank_number);
    sem_close(product_number);
    return 0;
}

在我的测试结果中,只有一个产品:808,但消费者得到两个产品:808和0;

$ sudo ./a.out
Produce queue[0]:808
Consume queue[0]:808
Consume queue[1]:0

我的代码有什么问题吗?

2 个答案:

答案 0 :(得分:1)

您的问题是您从未删除过您的信号量。因此,当你打开它们时,你会恢复一些旧/坏状态。尝试使用O_EXCL打开,您将能够观察到问题。

使用sem_unlink()编写一个简单的命令来删除它们,或者在使用semctl之前将它们初始化。

您还需要在sem_open而不是022 ...

中设置适当的值

Alos请注意,POSIX命名信号量的名称应以/开头。

将主页的开头更改为:

sem_unlink("blank_number");
sem_unlink("product_number");
//set blank_number to 1
blank_number = sem_open("blank_number", O_CREAT|O_EXCL, S_IRWXU, 1);
if(blank_number == SEM_FAILED){
    perror("open blank_number");
    return 1;
}
//set product_number to 0
product_number = sem_open("product_number", O_CREAT|O_EXCL, S_IRWXU, 0);
if(product_number == SEM_FAILED){
    perror("open product_number");
    return 1;
}

答案 1 :(得分:0)

也许尝试将sem_init与未命名的信号量一起使用而不是sem_open

sem_t semaphore;
int ret = sem_init(&semaphore, 0, 0);