Linux生产者消费者模型浅析
作者:pointer_y 发布时间:[ 2017/2/27 13:42:45 ] 推荐标签:操作系统 Linux
一、概念
生产者:产生数据的的模块。
消费者:处理数据的模块。
那么生产者产生数据之后,消费者怎么拿,从哪拿呢?所以,仅仅有这两个角色是不能完成我们期望的工作的。还需要一个缓冲区,像超市的货架一样,供货商(生产者)将商品摆到货架(缓冲区)上,购买者(消费者)从货架上拿走,这个货架也是必不可少的。
试想如果没有缓冲区,生产者生产一个数据之后,必须等待消费者消费完成,生产者才能继续生产,那么如果生产者很快,而消费者很慢,那么只能让生产者干等。这好比让CPU和外设直接打交道,如果没有缓存,还不得慢死,白白浪费CPU时间。
抽象出此模型如下:
接下来说明三种关系:
1.生产者与生产者之间:像供货商与供货商之间,存在明显的竞争关系,在操作系统上,我们称为互斥关系。
2.消费者与消费者之间:同样是互斥的。
3.生产者与消费者之间:首先必须保证,生产者在生产时,消费者不能来打扰,否则会出现数据二义性的问题。(生产者要往缓冲区里写入“1234”,刚写了12时消费者来缓冲区取数据了,那么它拿到的只能是12)。同时,消费者在消费时生产者也不能打扰,道理是一样的。所以,它们之间也有互斥的关系。除了互斥外,还必须保证生产者消费者按照一定的顺序访问资源。因为必须是让生产者先生产,消费者才能进行消费,类似于这样按照顺序访问资源成为同步,所以这两者之间还有同步的关系。
二、模型模拟
1.一个生产者一个消费者。
我们使用两个线程分别模拟生产者和消费者,使用单链表作为缓冲区,每次让生产者PUSH数据到链表头,消费者也每次从链表头部取POP数据。
完整的代码:
#include<stdio.h>
#include<pthread.h>
#include<stdlib.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,*pnode;
typedef struct Linklist
{
node * phead;
}Linklist,*pLinklist;
pnode creatNode(int data)
{
pnode newnode=(pnode)malloc(sizeof(node));
if(newnode==NULL)
{
perror("malloc");
exit(EXIT_FAILURE);
}
newnode->_data=data;
newnode->_next=NULL;
return newnode;
}
void initList(pLinklist plist)
{
assert(plist);
//pLinklist head=(pLinklist)malloc(sizeof(Linklist));
// plist=head;
plist->phead=NULL;
}
void pushHead(pLinklist list,int data)
{
assert(list);
pnode newnode=creatNode(data);
if(list->phead==NULL)
{
list->phead=newnode;
return;
}
newnode->_next=list->phead;
list->phead=newnode;
}
void popHead(pLinklist list,int* data)
{
assert(list);
if(list->phead==NULL)
{
printf("list empty!
");
return;
}
pnode del=list->phead;
*data=del->_data;
list->phead=del->_next;
del->_next=NULL;
free(del);
}
void destoryList(pLinklist list)
{
assert(list);
if(list->phead!=NULL)
{
pnode cur =list->phead;
while(cur)
{
pnode del=cur;
cur=cur->_next;
free(del);
del=NULL;
}
}
list->phead=NULL;
}
void showList(pLinklist list)
{
assert(list);
pnode cur=list->phead;
while(cur!=NULL)
{
printf("%d ",cur->_data);
cur=cur->_next;
}
printf("
");
}
void* producter_thread(void* arg)
{
pLinklist list=(pLinklist)arg;
while(1)
{
sleep(1);
pthread_mutex_lock(&mylock); //访问临界区前加锁
pushHead(list,rand()%1000);
pthread_cond_signal(&mycond); //生产完毕唤醒等待在该条件变量下的线程
pthread_mutex_unlock(&mylock); //访问结束解锁
printf("producter success %d
",list->phead->_data);
}
}
void* consumer_thread(void* arg)
{
pLinklist list=(pLinklist)arg;
while(1)
{
sleep(1);
pthread_mutex_lock(&mylock); //加锁
int data=0;
while(list->phead==NULL)
{
pthread_cond_wait(&mycond,&mylock); //若链表中无数据,则消费者需要等待。
}
popHead(list,&data);
pthread_mutex_unlock(&mylock); //解锁
printf("consumer success %d
",data);
}
}
int main()
{
Linklist list;
initList(&list);
pthread_t tid1,tid2;
pthread_create(&tid1,NULL,producter_thread,(void*)&list);//创建线程
pthread_create(&tid2,NULL,consumer_thread,(void*)&list);
pthread_join(tid1,NULL); //等待线程结束回收线程
pthread_join(tid2,NULL);
destoryList(&list);
return 0;
}
相关推荐
更新发布
功能测试和接口测试的区别
2023/3/23 14:23:39如何写好测试用例文档
2023/3/22 16:17:39常用的选择回归测试的方式有哪些?
2022/6/14 16:14:27测试流程中需要重点把关几个过程?
2021/10/18 15:37:44性能测试的七种方法
2021/9/17 15:19:29全链路压测优化思路
2021/9/14 15:42:25性能测试流程浅谈
2021/5/28 17:25:47常见的APP性能测试指标
2021/5/8 17:01:11