消费者/生产者计划陷入困境

时间:2016-07-10 15:19:15

标签: c

以下是示例消费者/生产者模型的代码:

int buffer[MAX];
int fill_ptr = 0;
int use_ptr = 0;
int count = 3;

void put(int value) {
    buffer[fill_ptr] = value;
    fill_ptr = (fill_ptr + 1) % MAX;
    count++;
}

int get() {
    int tmp = buffer[use_ptr];
    use_ptr = (use_ptr + 1) % MAX;
    count--;
    return tmp;
}

cond_t empty, fill;
mutex_t mutex;
void *producer(void *arg) {
    int i;
    for (i = 0; i < loops; i++) {
        pthread_mutex_lock(&mutex); // p1
        while (count == MAX) // p2
            pthread_cond_wait(&empty, &mutex); // p3
        put(i);// p4
        pthread_cond_signal(&fill); // p5
        pthread_mutex_unlock(&mutex); // p6
    }
}


void* consumer(void *arg) {
    int i;
    for (i = 0; i < loops; i++) {
        pthread_mutex_lock(&mutex); // c1
        while (count == 0) // c2
            pthread_cond_wait(&fill, &mutex); // c3
        int tmp = get(); // c4
        pthread_cond_signal(&empty); // c5
        pthread_mutex_unlock(&mutex); // c6
        printf("%d\n", tmp);
    }
}

但是,我认为这里存在问题。假设MAX = 3,并且最初缓冲区已满(count = 3),则消费者可以执行get()并向生产者发信号。在生成器收到信号后,它会唤醒并开始在缓冲区[0]中执行put()并保持互斥锁。

假设生产者刚陷入put();那么即使剩下2个资源,消费者也不能继续(因为互斥体由生产者持有)。

我的理解是否正确?如果是这样,那是不公平的,因为剩下2个资源可以消耗。

2 个答案:

答案 0 :(得分:1)

  

假设生产者刚陷入put();那么即使剩下2个资源,消费者也不能继续(因为互斥体由生产者持有)。

在持有互斥锁时,你绝不能做一些可能卡住的事情,而你的代码却没有。

答案 1 :(得分:1)

  

我的理解是否正确?

是和否。

是的,如果consumer调用producerput被卡住(例如进入无限循环),put将被卡住是正确的。

但是,您不能假设there are 2 resources left。在pthread_cond_signal读取所有3个三元素之前,producer不承诺consumer执行。所有你能知道的是consumer读取至少一个元素,但在生产者执行之前它可能读取2或甚至3。

  

如果是的话,这是不公平的......

不,这不是不公平的。它正是互斥体的用途,即确保只有一个线程可以访问共享资源。

因此,确保持有互斥锁的线程不会卡住是非常重要的!这是你作为程序员的责任。

注意:在您的情况下,内部没有任何内容可能导致线程卡住。