多线程队列

利用条件变量实现的多线程队列pqueue,

原理:

1. 在pqueue结构里定义了两个条件变量m_full和m_free,两个计数器m_freewait和m_fullwait。

2. 生产者线程向队列插入数据前,判断队列是否满,如果满则让该线程等待在m_full,等待消费者线程从队列取元素,计数器m_fullwait自增,用来表示等待m_full的生产者线程数。

3. 生产者线程向队列中写入数据后,检测m_freewait计数器看是否有线程等待在m_free,如果有,则pthread_cond_signal(&m_free)发送一个信号,唤醒一个等待在m_free的线程,然后m_freewait自减。

4. 消费者线程从队列中取数据前,判断队列是否空,如果空则该线程等待在m_free;等待生产者线程往队列中存数据,计数器m_freewait自增,表示等待m_free的消费者线程数

5. 消费者线程从队列中取出数据后,检测m_fullwait计数器看是否有线程等待在m_full,如果与,则pthread_cond_signal(&m_full)发动一个信号,唤醒一个等待在m_full的线程,然后m_fullwait自减。

 

 

代码如下:

pqueue.h

#ifndef _THREAD_QUEUE_H_ 
#define _THREAD_QUEUE_H_

#include <stdlib.h>
#include <pthread.h>

typedef struct _node {
	int m_data;
	struct _node* m_next;
} node_t;

typedef struct _queue {
	node_t *m_head;
	node_t **m_tail;
	int m_size;
	int m_maxsize;
	int m_freewait;          // the number of waiting thread when queue is free
	int m_fullwait;          // the number of waiting thread when queue is full
	pthread_cond_t m_full;
	pthread_cond_t m_free;
	pthread_mutex_t m_lock;
} queue_t;

void* queue_init (int size);
void  queue_del  (void* que);
int   queue_put  (void* que, int data);
int   queue_get  (void* que, int* data);

#endif


pqueue.c

#include "pqueue.h"
#include <assert.h>

void* queue_init (int size) {
	queue_t* q;
	assert (size > 0);
	q = (queue_t*)malloc(sizeof(queue_t));
	q->m_head = 0;
	q->m_tail = &(q->m_head);
	q->m_size = 0;
	q->m_maxsize = size;
	q->m_freewait = 0;
	q->m_fullwait = 0;
	pthread_cond_init (&(q->m_full),0);
	pthread_cond_init (&(q->m_free),0);
	pthread_mutex_init (&(q->m_lock),0);
	return q;
}

void queue_del (void* que) {
	queue_t* queue = (queue_t*) que;
	node_t* p, *q;
	pthread_mutex_lock (&(queue->m_lock));
	assert (!(queue->m_freewait));
	assert (!(queue->m_fullwait));
	for (p = queue->m_head; p; p = q) {
		q = p->m_next;
		free (p);
	}
	pthread_mutex_unlock (&(queue->m_lock));
	pthread_mutex_destroy (&(queue->m_lock));
	pthread_cond_destroy (&(queue->m_free));
	pthread_cond_destroy (&(queue->m_full));
	free (queue);
}

int queue_put (void* que, int data) {
	queue_t* queue = (queue_t*)que;
	node_t* node = (node_t*)malloc (sizeof(node_t));
	node->m_data = data;
	node->m_next = 0;
	
	pthread_mutex_lock (&(queue->m_lock));
	while (queue->m_size >= queue->m_maxsize) {
		queue->m_fullwait++;
		pthread_cond_wait (&(queue->m_full),&(queue->m_lock));
	}
	queue->m_size ++;
	*(queue->m_tail) = node;
	if (queue->m_freewait > 0) {
		pthread_cond_signal (&(queue->m_free));
		queue->m_freewait --;
	}
	pthread_mutex_unlock (&(queue->m_lock));
	return 0;
}

int queue_get (void* que, int* data) {
	queue_t* queue = (queue_t*)que;
	node_t* node;

	pthread_mutex_lock (&(queue->m_lock));
	while (queue->m_size == 0) {
		queue->m_freewait ++;
		pthread_cond_wait (&(queue->m_free), &(queue->m_lock));
	}
	node = queue->m_head;
	queue->m_head = node->m_next;
	if (!queue->m_head) {
		queue->m_tail = &(queue->m_head);
	}
	queue->m_size --;
	if (queue->m_fullwait > 0) {
		pthread_cond_signal (&(queue->m_full));
		queue->m_fullwait--;
	}
	pthread_mutex_unlock (&(queue->m_lock));
	if (data) {
		*data = node->m_data;
	}
	free (node);
}


下面是一个例子,主线程做生产者,15个子线程做做消费者

#include <stdio.h>
#include "pqueue.h"

pthread_t tarr[15];
queue_t *g_queue;

void* thr_fn (void* arg) {
	pthread_t tid = pthread_self();
	for (;;) {
		int data;
		queue_get (g_queue, &data);
		printf ("tid = %u, data = %d\n",(unsigned int)tid, data);
		sleep (1);
	}
}

int main () {
	int i = 0;
	g_queue = queue_init (30);
	for (i = 0; i < 15; ++i) {
		pthread_create (&tarr[i],0, thr_fn, 0);
	}
	for (;;) {
		queue_put (g_queue, rand());
	}
}


 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值