【问题标题】:Strange deadlock in producer-consumer queue生产者-消费者队列中的奇怪死锁
【发布时间】:2016-08-26 09:14:15
【问题描述】:

使用 C 的 pthread 库,我正在尝试实现一个简单的生产者-消费者模式。

生产者生成随机数并将它们放入这样的队列中

typedef struct {
    int q[MAX_QUEUE];
    int head;
    int tail;
} queue;

消费者只需一个接一个地获取数字并将它们打印到标准输出。同步是通过一个mutex 和两个条件变量完成的:empty_queue(如果队列为空则暂停消费者)和full_queue(如果队列满则暂停生产者)。问题是两个线程在达到MAX_QUEUEelements 生产/消费时都会暂停自己,因此它们会进入死锁情况。我认为我所做的一切都是正确的,我无法弄清楚我做错了什么。

制作人:

void* producer(void* args) {
    unsigned seed = time(NULL);
    int random;
    queue *coda = (queue *) args;

    while(1) {
        Pthread_mutex_lock(&queue_lock);
        while(coda->head == MAX_QUEUE-1) { // Full Queue
            printf("Suspending producer\n");
            fflush(stdout);
            Pthread_cond_wait(&full_queue, &queue_lock);
        }

        random = rand_r(&seed) % 21;
        enqueue(coda, random);

        Pthread_cond_signal(&empty_queue);
        Pthread_mutex_unlock(&queue_lock);

        sleep(1);
    }

    return NULL;
}

消费者:

void* consumer(void* args) {
    queue *coda = (queue *) args;
    int elem;

    while(1) {
        Pthread_mutex_lock(&queue_lock);
        while(coda->head == coda->tail) { // Empty Queue
            printf("Suspending Consumer\n");
            fflush(stdout);
            Pthread_cond_wait(&empty_queue, &queue_lock);
        }

        elem = dequeue(coda);
        printf("Found %i\n",elem);

        Pthread_cond_signal(&full_queue);
        Pthread_mutex_unlock(&queue_lock);
    }

    return NULL;
}

入队/出队例程

static void enqueue(queue *q, int elem) {
    q->q[(q->tail)] = elem;
    (q->tail)++;
    if(q->tail == MAX_QUEUE)
        q->tail = 0;
}

static int dequeue(queue *q) {
    int elem = q->q[(q->head)];
    (q->head)++;
    if(q->head == MAX_QUEUE)
        q->head = 0;
    return elem;
}

Pthread_* 只是标准 pthread_* 库函数的包装函数。 输出(MAX_QUEUE = 10):

Suspending Consumer
Found 16
Suspending Consumer
Found 7
Suspending Consumer
Found 5
Suspending Consumer
Found 6
Suspending Consumer
Found 17
Suspending Consumer
Found 1
Suspending Consumer
Found 12
Suspending Consumer
Found 14
Suspending Consumer
Found 11
Suspending Consumer
Suspending producer

【问题讨论】:

    标签: c multithreading pthreads mutex producer-consumer


    【解决方案1】:
    coda->head == MAX_QUEUE-1
    

    这不会检查队列是否已满。有两个变量可以描述队列的状态,headtail

    coda->head == coda->tail
    

    这会正确检查队列是否为空。请注意在检查中如何使用这两个变量。

    【讨论】:

    • 使用(coda->tail+1)%MAX_QUEUE == coda->head解决。感谢您的建议。
    猜你喜欢
    • 2013-03-06
    • 2011-05-04
    • 1970-01-01
    • 2012-05-21
    • 1970-01-01
    • 2011-02-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多