使用条件变量实现生产者消费者模型

生产者消费者模型是多线程案例中经常用到的一种模型,有专门的线程在负责生产产品(这个产品指代程序所需的数据、文件等等),有专门的线程在负责取出生产出来的产品用以提供程序使用(消费)。因为生产和消费在程序中是不定时间的,我们也无法确定什么时候需要生产产品,什么时候需要消费产品。所以就有了使用条件变量实现的解决方案。


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

struct tag_product {
	struct tag_product* next;
	int data;
};
struct tag_product* head;

// 初始化条件变量和锁的另外一种方式,也可以使用init
pthread_cond_t product = PTHREAD_COND_INITIALIZER;
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;

void* producer(void* arg)
{
	struct tag_product* cur; 
	while (1)
	{
		// 加锁
		pthread_mutex_lock(&mutex);
		// 创建新节点
		cur = (struct tag_product*)malloc(
				sizeof(struct tag_product));
		// 让新节点先有所指向
		cur->next = head->next;
		// 让头节点指向新来的节点
		head->next = cur;

		// 解锁
		pthread_mutex_unlock(&mutex);
		// 让其他线程得到新产品通知
		pthread_cond_signal(&product);
		sleep(rand() % 5);
	}
	return (void*)0;
}

void* consumer(void* arg)
{
	printf("consumer thread = %d\n", (unsigned int)pthread_self());
	struct tag_product* tmp;
	while(1)
	{
		// 加锁
		pthread_mutex_lock(&mutex);
		while(head->next == NULL)
		{
			// 等待,循环判断头节点是否有下一个节点
			pthread_cond_wait(&product, &mutex);
		}
		// 有新节点则备份第一个节点
		tmp = head->next;
		// 让头节点跳过第一个节点
		head->next = tmp->next;
		// 打印第一个节点的数据
		printf("consumer %d\n", tmp->data);
		
		// 释放第一个节点
		free(tmp);
		// 解锁
		pthread_mutex_unlock(&mutex);
		sleep(rand() % 5);
	}
	return (void*)0;
}

int main(int argc, char* argv[])
{
	pthread_t pid, cid;
	srand(time(NULL));

	head = (struct tag_product*)malloc(sizeof(struct tag_product));
	head->next = NULL;

	pthread_create(&pid, NULL, producer, (void*)1);
	pthread_create(&cid, NULL, consumer, (void*)1);

	pthread_join(pid,NULL);
	pthread_join(cid,NULL);
	return 0;
}

 

发表评论