使用POSIX线程解决“生产者/消费者”问题

/*
*	File	: pc.cpp
*
*	Title	: Demo Producer/Consumer.
*
*	Short	: A solution to the producer consumer problem using pthreads.
*			This is a simple FIFO pipe between two tasks. The primary problem is
*			ensuring that the producer blocks if the FIFO is full, and the consumer
*			blocks if it is empty, and avoiding data-races along the way. A secondary
*			concern is that there is as little interference between the two tasks as
*			possible. 
*
*	Author	: Andrae Muys
*
*	Date	: 18 September 1997
*/

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

#ifdef _WIN32
#	include <windows.h>
#	define SLEEP(ms) Sleep(ms)
#elif defined(LINUX)
#	include <unistd.h>
#	define SLEEP(ms) sleep(ms)
#endif

#define QUEUE_SIZE	10
#define LOOP		20

void* producer (void *args);
void* consumer (void *args);

typedef struct
{
	int buf[QUEUE_SIZE];
	long head, tail;
	bool full, empty;
	pthread_mutex_t *mutex;
	pthread_cond_t *notFull, *notEmpty;
} Queue;

Queue*	queueInit (void);
void	queueDelete (Queue *q);
void	queueAdd (Queue *q, int in);
void	queueDel (Queue *q, int *out);

int main(int argc, char* argv[])
{
	Queue* fifo = queueInit ();
	assert(fifo !=  NULL);

	pthread_t pro, con;
	pthread_create (&pro, NULL, &producer, fifo);
	pthread_create (&con, NULL, &consumer, fifo);
	pthread_join (pro, NULL);
	pthread_join (con, NULL);
	queueDelete (fifo);
	return 0;
}

void* producer (void *q)
{
	Queue* fifo = (Queue *)q;

	for (int i = 0; i < LOOP; i++)
	{
		// 临界区操作:若队列未满,添加新数据
		pthread_mutex_lock (fifo->mutex);
		while (fifo->full)
		{
			printf ("producer: Queue FULL.\n");
			pthread_cond_wait (fifo->notFull, fifo->mutex);
		}
		queueAdd (fifo, i);
		pthread_mutex_unlock (fifo->mutex);

		// 数据添加结束,发“队列有数据”信号
		pthread_cond_signal (fifo->notEmpty);
		SLEEP (100);
	}

	// 与上面类似
	for (int i = 0; i < LOOP; i++)
	{
		pthread_mutex_lock (fifo->mutex);
		while (fifo->full)
		{
			printf ("producer: Queue FULL.\n");
			pthread_cond_wait (fifo->notFull, fifo->mutex);
		}
		queueAdd (fifo, i);
		pthread_mutex_unlock (fifo->mutex);
		pthread_cond_signal (fifo->notEmpty);
		SLEEP (200);
	}
	return (NULL);
}

void* consumer (void *q)
{
	int d;

	Queue *fifo = (Queue *)q;

	for (int i = 0; i < LOOP; i++)
	{
		// 临界区操作:若队列不空,则取出数据
		pthread_mutex_lock (fifo->mutex);
		while (fifo->empty)
		{
			printf ("consumer: Queue EMPTY.\n");
			pthread_cond_wait (fifo->notEmpty, fifo->mutex);
		}
		queueDel (fifo, &d);
		pthread_mutex_unlock (fifo->mutex);

		// 取完数据,发“队列不满”信号
		pthread_cond_signal (fifo->notFull);
		printf ("consumer: recieved %d.\n", d);
		SLEEP(200);
	}

	// 与上面类似
	for (int i = 0; i < LOOP; i++)
	{
		pthread_mutex_lock (fifo->mutex);
		while (fifo->empty)
		{
			printf ("consumer: Queue EMPTY.\n");
			pthread_cond_wait (fifo->notEmpty, fifo->mutex);
		}
		queueDel (fifo, &d);
		pthread_mutex_unlock (fifo->mutex);
		pthread_cond_signal (fifo->notFull);
		printf ("consumer: recieved %d.\n", d);
		SLEEP (50);
	}
	return (NULL);
}

Queue *queueInit (void)
{
	Queue *q = (Queue *)malloc (sizeof (Queue));
	if (q == NULL) return (NULL);

	q->empty = true;
	q->full = false;
	q->head = 0;
	q->tail = 0;

	q->mutex = (pthread_mutex_t *) malloc (sizeof (pthread_mutex_t));
	pthread_mutex_init (q->mutex, NULL);
	q->notFull = (pthread_cond_t *) malloc (sizeof (pthread_cond_t));
	pthread_cond_init (q->notFull, NULL);
	q->notEmpty = (pthread_cond_t *) malloc (sizeof (pthread_cond_t));
	pthread_cond_init (q->notEmpty, NULL);
	
	return (q);
}

void queueDelete (Queue *q)
{
	pthread_mutex_destroy (q->mutex);
	free (q->mutex);	

	pthread_cond_destroy (q->notFull);
	free (q->notFull);

	pthread_cond_destroy (q->notEmpty);
	free (q->notEmpty);

	free (q);
}

void queueAdd (Queue *q, int in)
{
	q->buf[q->tail] = in;
	q->tail++;
	if (q->tail == QUEUE_SIZE)	// 循环队列
		q->tail = 0;

	if (q->tail == q->head)		// 添加数据时“触顶”
		q->full = true;
	q->empty = false;

	return;
}

void queueDel (Queue *q, int *out)
{
	*out = q->buf[q->head];
	q->head++;
	if (q->head == QUEUE_SIZE)	// 循环队列
		q->head = 0;

	if (q->head == q->tail)		// 取出数据时“触底”
		q->empty = true;
	q->full = false;

	return;
}


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值