Linux——条件变量实现生产者消费者模型

1、条件变量的生产者消费模型流程分析

在这里插入图片描述

2、条件变量实现生产者消费者模型

// 1, 创建两个线程,一个生产者线程,一个消费者线程
//2,创建完线程之后就可以直接写回收线程部分的代码,养成习惯
//3,分别写两个线程的回调函数
//4,去构造条件变量的内容,这边写一个放内容的msg结构体,定义结构体类型的全局变量头指针
//3.1,开始写生产者消费者的操作,两者都需要对内容进行加锁,因此先去定义一个互斥量
//5, 定义互斥量(全局),在使用互斥量之前需要先初始化,可以动态初始化也可以用宏PTHREAD_MUTEX_INITIALIZER静态初始化
//6,同理,定义并初始化一个条件变量,用于通知是已经生产数据了
//3.2, 接着写生产者,生产者一上来就是①生产:malloc一个节点,节点中添值,将数据挂到公共区域上;;挂之前②加锁;③链表头插法挂上去 ④挂好解锁 ⑤通知pthread_cond_signal(&has_data);//唤醒阻塞在条件变量has_data上的线程,即生产者
//3.3, 写consumer,有了互斥量,①先加锁②判断公共区域上是否有数据,没有就要条件变量去等待(阻塞并解锁),有数据就直接拿数据③或者是被唤醒拿数据,从链表中拿数据 ④解锁free内存 ⑤free内存

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

void err_thread(int ret, char *str)
{
	if(ret != 0)
	{
		fprintf(stderr, "%s:%s\n", str, stderror(ret));
		pthread_exit(NULL);
	}
}
struct msg
{
	int num;
	struct msg* next;
};
struct msg *head;//头指针
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;//定义且初始化互斥量
phread_cond_t has_data = PTHREAD_COND_INITIALIZER;//定义并初始化条件变量
void *producer(void *arg)
{
	struct msg *mp = malloc(sizeof(struct msg));//产生一个节点
	mp->num = rand() %1000 +1;//模拟生产一个数据
	pthread_mutex_lock(&mutex);//挂数据前先加锁
	mp->next = head;
	head = mp;//写公共区域操作
	pthread_mutex_unlock(&mutex);//解锁互斥量
	pthread_cond_signal(&has_data);//唤醒阻塞在条件变量has_data上的线程,即生产者
	sleep(rand() % 3);
	return NULL;
}

void *consumer(void *arg)
{
	struct msg *mp;
	pthread_mutex_lock(&mutex);//给互斥量加锁,,为了突出逻辑就不检查返回值了,但是正经项目中一定要检查返回值
	if(head == NULL)//头指针为空的时候才需要等待,头指针不为空表示是有数据的,就直接拿好了;;;;;//当多个消费者时,就需要用while判断了
	{
		pthread_cond_wait(&has_data, &mutex);//阻塞等待条件变量,并解锁
	}//pthread_con_wait返回时重新加锁
	//被唤醒就说明公共区域已经有内容了,条件变量会自动加锁(上一个函数的作用
	mp = head;
	head = head->next;//取数据
	pthread_mutex_unlock(&mutex);//解锁互斥量
	free(mp);
	sleep(rand()%3);//sleep时,cup会转到另一个线程处,这边就是交给生产者
	
	return NULL;
}

int main(int argc, char *argv[])
{	
	int ret;
	srand(time(NULL));//⭐
	pthread_t pid, cid;//生产者、消费者
	ret = pthread_create(&pid, NULL, producer, NULL);//创建生产者
	if(ret != 0)
	{
		err_thread(ret, "pthread_create producer error");
	}
	ret = pthread_create(&cid, NULL, consumer, NULL);//创建消费者
	if(ret != 0)
	{
		err_thread(ret, "pthread_create consumer error");
	}
	//回收线程
	pthread_join(pid,NULL);
	pthread_join(cid,NULL);
	return 0;
}

当一个生产者多个消费者时:

原创文章 119 获赞 27 访问量 5983

猜你喜欢

转载自blog.csdn.net/qq_37299596/article/details/105950533