在c中实现共享队列时出现死锁

时间:2017-06-20 09:55:44

标签: c multithreading pthreads synchronisation

#include "pc.h"
#include <stdlib.h>
#include <string.h>


/**

Contents of pc.h

#ifndef __PC__H
#define __PC__H

#include <pthread.h>

#define ITEM(q, i) (q->pc_buffer + q->pc_item_size * i)

struct pc_queue_t {
    void *pc_buffer;
    size_t pc_next_full, pc_next_empty, pc_cur_size, pc_max_size, pc_item_size;
    pthread_cond_t pc_empty, pc_full;
    pthread_mutex_t pc_mutex;
};

struct pc_queue_t *alloc_q(size_t item_size, size_t no_of_items);

void pc_insert(struct pc_queue_t *q, void *item);

void *pc_remove(struct pc_queue_t *q);

void free_queue(struct pc_queue_t *q);


#endif

**/


struct pc_queue_t *alloc_q(size_t item_size, size_t no_of_items) {
    struct pc_queue_t *q   = (struct pc_queue_t *)malloc(sizeof(struct pc_queue_t));
    q->pc_buffer    = malloc(item_size * no_of_items);
    q->pc_next_full = q->pc_next_empty = q->pc_cur_size = 0;
    q->pc_item_size = item_size;
    q->pc_max_size  = no_of_items;
    // q->pc_empty     = PTHREAD_COND_INITIALIZER;
    // q->pc_full      = PTHREAD_COND_INITIALIZER;
    // q->pc_mutex     = PTHREAD_MUTEX_INITIALIZER;
    pthread_cond_init(&q->pc_empty, NULL);
    pthread_cond_init(&q->pc_full, NULL);
    pthread_mutex_init(&q->pc_mutex, NULL);
    return q;
}


void pc_insert(struct pc_queue_t *q, void *item) {
    pthread_mutex_lock(&q->pc_mutex);
    while(q->pc_cur_size == q->pc_max_size) 
        pthread_cond_wait(&q->pc_empty, &q->pc_mutex);
    q->pc_cur_size++;
    memcpy(ITEM(q, q->pc_next_empty), item, q->pc_item_size);
    q->pc_next_empty = (q->pc_next_empty + 1) % q->pc_max_size;
    pthread_mutex_unlock(&q->pc_mutex);
    pthread_cond_signal(&q->pc_full);
}

void *pc_remove(struct pc_queue_t *q) {
    pthread_mutex_lock(&q->pc_mutex);
    while(q->pc_cur_size == 0) 
        pthread_cond_wait(&q->pc_full, &q->pc_mutex);
    q->pc_cur_size--;
    void *ret_item = ITEM(q, q->pc_next_full);
    q->pc_next_full = (q->pc_next_full + 1) % q->pc_max_size;
    pthread_mutex_unlock(&q->pc_mutex);
    pthread_cond_signal(&q->pc_empty);
    return ret_item;
}

void free_queue(struct pc_queue_t *q) {
    if(!q) return;
    free(q->pc_buffer);
    free(q);
}

我试图用c中的互斥和条件变量来解决生产者 - 消费者同步问题。而且我被卡住了。有人可以帮我弄清楚上面给出的代码有什么问题。 pc_insert方法效果很好。但由于某种原因,pc_remove方法永远不会从它的第一次调用返回。可能是什么问题?

这就是我使用它的方式 - &gt;

typedef struct pc_queue_t shared_q;

void *consumer(void *buf) {
    shared_q *q = (shared_q *)buf;
    while(true) {
        int *p = (int *)pc_remove(q);
        printf("Removed %d\n", *p);
        free(p);
        sleep(1);
    }
    return NULL;
}

void *producer(void *buf) {
    shared_q *q = (shared_q *)buf;
    int data = 0;
    while(true) {
        int *p = (int *)malloc(sizeof(int));
        *p = data++;
        pc_insert(q, p);
        printf("Inserted %d\n", data);
        sleep(1);
    }
    return NULL;
}

int main() {
    shared_q *q = alloc_q(sizeof(int), 5);
    pthread_t t1, t2;
    int succ = pthread_create(&t1, NULL, producer, q) &&
            pthread_create(&t2, NULL, consumer, q);
    if(succ) {
        perror("Failed to create threads!");
        exit(1);
    }
    pthread_join(t1, NULL);
    pthread_join(t2, NULL);
    return 0;
}

1 个答案:

答案 0 :(得分:1)

哎呀..我想我明白了。 这就是这条线..

 int succ = pthread_create(&t1, NULL, producer, q) &&
            pthread_create(&t2, NULL, consumer, q);

我忘了pthread_create在成功时返回0。消费者从未因短路而开始。