c语言实现多线程下的链表队列

项目中需要一个链表,线程A进行入队操作(生产者),线程B进行查询、出队操作(消费者),同时希望线程B在队列为空时阻塞,降低cpu负载,因此考虑用pthread_cond_wait进行实现:

主要实现功能:

1)出队和入队的加锁

2)当有元素入队时唤醒线程B

3)队列为空时线程B进入休眠


头文件:

#ifndef Queue_H
#define Queue_H
#include 
#include 
typedef char* Frame;
typedef struct node * PNode;
typedef struct node
{
	Frame frame;
	PNode next;
}Node;

typedef struct
{
	PNode front;
	PNode rear;
	int size;
	pthread_mutex_t q_lock;
	pthread_cond_t cond;
}Queue;

/*构造一个空队列*/
Queue *InitQueue();

/*销毁一个队列*/
void DestroyQueue(Queue *pqueue);

/*清空一个队列*/
void ClearQueue(Queue *pqueue);

/*判断队列是否为空*/
int IsEmpty(Queue *pqueue);

/*返回队列大小*/
int GetSize(Queue *pqueue);

/*返回队头元素*/
PNode GetFront(Queue *pqueue, Frame *frame);

/*返回队尾元素*/
PNode GetRear(Queue *pqueue, Frame *frame);

/*将新元素入队*/
PNode EnQueue(Queue *pqueue,Frame frame);

/*队头元素出队*/
PNode DeQueue(Queue *pqueue);

/*遍历队列并对各数据项调用visit函数*/
void QueueTraverse(Queue *pqueue,void (*visit)());

#endif

c文件:

#include"Queue.h"

/*构造一个空队列*/
Queue *InitQueue()
{
	Queue *pqueue = (Queue *)malloc(sizeof(Queue));
	if(pqueue!=NULL)
	{
		pqueue->front = NULL;
		pqueue->rear = NULL;
		pqueue->size = 0;
		pthread_mutex_init(&pqueue->q_lock, NULL);		
		pthread_cond_init(&pqueue->cond, NULL);
	}
	return pqueue;
}

/*销毁一个队列*/
void DestroyQueue(Queue *pqueue)
{
	if(!pqueue)
		return;
	ClearQueue(pqueue);
	pthread_mutex_destroy(&pqueue->q_lock);
	pthread_cond_destroy(&pqueue->cond);
	free(pqueue);
	pqueue = NULL;
}

/*清空一个队列*/
void ClearQueue(Queue *pqueue)
{
	while(!IsEmpty(pqueue)) {
		DeQueue(pqueue);
	}

}

/*判断队列是否为空*/
int IsEmpty(Queue *pqueue)
{
	if(pqueue->front==NULL&&pqueue->rear==NULL&&pqueue->size==0)
		return 1;
	else
		return 0;
}

/*返回队列大小*/
int GetSize(Queue *pqueue)
{
	return pqueue->size;
}

/*返回队头元素*/
PNode GetFront(Queue *pqueue, Frame *frame)
{
	pthread_mutex_lock(&pqueue->q_lock);
	/*
	if(!IsEmpty(pqueue))
	{
		*frame = pqueue->front->frame;
	}else {
		pthread_cond_wait(&pqueue->cond, &pqueue->q_lock);
	}*/
	while(IsEmpty(pqueue))
		pthread_cond_wait(&pqueue->cond, &pqueue->q_lock);
	*frame = pqueue->front->frame;
	pthread_mutex_unlock(&pqueue->q_lock);
	return pqueue->front;//---->此处有bug,队列为空时,在锁释放后,pqueue->front可能被入队操作赋值,出现frame等于NULL,而pqueue->front不等于NULL
}

/*返回队尾元素*/

PNode GetRear(Queue *pqueue, Frame *frame)
{
	if(!IsEmpty(pqueue)) {
		*frame = pqueue->rear->frame;
	}
	return pqueue->rear;
}

/*将新元素入队*/
PNode EnQueue(Queue *pqueue, Frame frame)
{
	PNode pnode = (PNode)malloc(sizeof(Node));
	if(pnode != NULL) {
		pnode->frame = frame;
		pnode->next = NULL;
		
		pthread_mutex_lock(&pqueue->q_lock);
		if(IsEmpty(pqueue)) {
			pqueue->front = pnode;
		} else {
			pqueue->rear->next = pnode;
		}
		pqueue->rear = pnode;
		pqueue->size++;
		pthread_cond_signal(&pqueue->cond);
		pthread_mutex_unlock(&pqueue->q_lock);
	}
	return pnode;
}

/*队头元素出队*/
PNode DeQueue(Queue *pqueue)
{
	PNode pnode = pqueue->front;
	pthread_mutex_lock(&pqueue->q_lock);
	if(!IsEmpty(pqueue)) {
		pqueue->size--;
		pqueue->front = pnode->next;
		free(pnode);
		if(pqueue->size==0)
			pqueue->rear = NULL;
	}
	pthread_mutex_unlock(&pqueue->q_lock);
	return pqueue->front;
}

/*遍历队列并对各数据项调用visit函数*/
void QueueTraverse(Queue *pqueue, void (*visit)())
{
	PNode pnode = pqueue->front;
	int i = pqueue->size;
	while(i--)
	{
		visit(pnode->frame);
		pnode = pnode->next;
	}
		
}


你可能感兴趣的:(linux,c)