linux下实现生产者-消费者问题


生产者(producer)和消费者(consumer)问题是并发处理中最常见的一类问题,是一个多线程同步问题的经典案例。

        可以这样描述这个问题,有一个或者多个生产者产生某种类型的数据,并放置在固定大小的缓冲区中,一个消费者从缓冲区中取数据,每次取一项,系统必须保证对缓冲区的重复操作,任何时候,只有一个生产者或者消费者可以访问缓冲区;同时,消费者只能在缓冲区不为空的时候从缓冲区中读数据,生产者只能在缓冲区不为满的时候向缓冲区写入数据。

上面的问题总结起来有两点:

       第一是缓冲区的互斥访问问题,任意时刻最多只能有一个线程访问缓冲区,Linux下可以使用互斥量pthread_mutex_t对访问缓冲区的临界区代码进行保护。

      第二是生产者和消费者对缓冲区访问的同步问题,生产者在缓冲区满时不能向缓冲区中写入数据,同时消费者在缓冲区空时不能读取数据,这里采用条件变量来对缓冲区进行同步。

实现代码如下:

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

pthread_mutex_t mylock = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t mycond = PTHREAD_COND_INITIALIZER;
typedef struct _node
{
	int data;
	struct _node *next;
}node_t, *node_p, **node_pp;

node_p alloc_node(int data)
{
	node_p _n = (node_p)malloc(sizeof(node_t));
	if(_n == NULL)
	{
		perror("malloc");
		return NULL;
	}
	_n->data = data;
	_n->next = NULL;
	return _n;
}

void del_node(node_p _n)
{
	assert(_n);
	free(_n);
}

int is_empty(node_p list)
{
	assert(list);
	if(list->next)
	{
		return 0;
	}
	else
		return 1;
}

void show_list(node_p list)
{
	assert(list);
	node_p start = list->next;
	while(start)
	{
		printf("%d\n",start->data);
		start = start->next;
	}
	printf("\n");
}

void init_list(node_pp _h)
{
	*_h = alloc_node(0);
}

void Push(node_p list, int data)
{
	assert(list);
	node_p new_node = alloc_node(data);
	new_node->next = list->next;
	list->next = new_node;
}

void Pop(node_p list, int *data)
{
	assert(list);
	assert(data);
	if(is_empty(list))
	{
		printf("list is empty\n");
	}
	node_p _n = list->next;
	list->next = _n->next;
	*data = _n->data;
	del_node(_n);
}

void destory_list(node_p list)
{
	assert(list);
	int data = 0;
	while(!is_empty(list))
	{
		Pop(list, &data);
	}
	del_node(list);
}

void test_list(node_p head)
{	
	int i = 0;
	for( ; i<10; i++)
	{
		Push(head, i);
		sleep( 1 );
		show_list(head);
	}

	int data = 0;
	for(; i>=5; i--)
	{
		Pop(head, &data);
		sleep(1);
		show_list(head);
	}
}

void *thread_product(void* arg)
{
	node_p head = (node_p)arg;
	while(1)
	{
		usleep(100621);
		int data = rand()%10000;
		pthread_mutex_lock(&mylock);
		Push(head, data);
		pthread_mutex_unlock(&mylock);
		pthread_cond_signal(&mycond);
		printf("product data is: %d\n", data);
	}
}

void *thread_consumer(void* arg)
{
	node_p head = (node_p)arg;
	int data = 0;
	while(1)
	{
		pthread_mutex_lock(&mylock);
		while(is_empty(head))
		{
			pthread_cond_wait(&mycond, &mylock);
		}
		Pop(head, &data);
		pthread_mutex_unlock(&mylock);
		printf("consumer done, data is: %d\n",data);
	}
}

int main()
{
	node_p head = NULL;
	init_list(&head);
    //test_list(head);
	pthread_t tid1, tid2;
	pthread_create(&tid1, NULL, thread_product, (node_p)head);	
	pthread_create(&tid2, NULL, thread_consumer, (node_p)head);

	pthread_join(tid1, NULL);
	pthread_join(tid2, NULL);

	destory_list(head);
	show_list(head);
	pthread_mutex_destroy(&mylock);
	pthread_cond_destroy(&mycond);
	show_list(head);
	//sleep(1);
	return 0;
}

实现结果 如下图所示:

因为我在编程时用了产生随机数的函数rand(),所以数字产生是随机的。



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值