用条件变量实现阻塞队列

#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
const int NUM = 20; 
struct node
{
    int val;
    struct node *next;
};

void node_ini(struct node *n, int i)
{
    n->val = i;
    n->next = NULL;
}

void node_destroy(struct node *n) 
{
    free(n);
}

struct block_queue
{
     struct node *head; 
     struct node *tail; 
     pthread_cond_t notempty; //非空条件变量
     pthread_mutex_t mutex; 
};

struct block_queue* block_queue_init()
{
    struct block_queue * q = (struct block_queue*)malloc(sizeof(struct block_queue));
    q->head = NULL;
    q->tail = NULL;
    pthread_cond_init(&q -> notempty, NULL);
    pthread_mutex_init(&q -> mutex, NULL);
    return q;
}

void block_queue_destroy(struct block_queue * q)
{
    pthread_cond_destroy(&q->notempty);
    pthread_mutex_destroy(&q->mutex);
    free(q);
}

//尾部插入元素
void block_queue_push(struct block_queue *q, int i) 
{
    pthread_mutex_lock(&q->mutex);
    struct node *n = (struct node*)malloc(sizeof(struct node));
    node_ini(n, i);

    if(q->tail == NULL)
    {
        q->tail = n;
    }
    else
    {
        q->tail->next = n;
        q->tail = n;
    }
    if(q->head == NULL)
    {
        q->head = n;
    }
    pthread_mutex_unlock(&q->mutex);
    //通知等待notempty的线程,队列不空
    pthread_cond_signal(&q->notempty);
}

//头部取元素
int block_queue_pop(struct block_queue *q) 
{
    pthread_mutex_lock(&q->mutex);
    while (q->head == NULL) {
        printf("queue is empty, wait\n");
        pthread_cond_wait(&q->notempty, &q->mutex);
    }
    struct node *p = q->head;
    q->head = p->next;
    pthread_mutex_unlock(&q->mutex);
    int v = p->val;
    free(p);
    return v;
}

void* producer(void* args)
{
    struct block_queue * queue = (struct block_queue *)args;
    for (int i = 0; i < NUM; ++i) {
        block_queue_push(queue, i);
        printf("push:%d\n", i);
    }
    return NULL;
}

void* consumer(void* args)
{
    struct block_queue * queue = (struct block_queue*)args;
    for (int i = 0; i < NUM; ++i) {
        int v = block_queue_pop(queue);
        printf("pop:%d\n", v);
    }
    return NULL;
}

int main()
{
    struct block_queue *queue = block_queue_init();
    printf("Begin\n");

    pthread_t pro_thread;
    pthread_t con_thread;

    pthread_create(&pro_thread, NULL, producer, queue);
    pthread_create(&con_thread, NULL, consumer, queue);

    pthread_join(pro_thread, NULL);
    pthread_join(con_thread, NULL);
    printf("End\n");
}

点赞