基于单链表和基于环形队列的生产者消费者模型_c++ 生产者消费者模型环形队列

img
img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上C C++开发知识点,真正体系化!

由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新

如果你需要这些资料,可以戳这里获取

}

void initList(node_pp _h)//初始化链表
{
*_h=alloc_node(0);
}

void pushFront(node_p h,int data)//向链表头部插入元素
{
node_p _n=alloc_node(data);
_n->next=h->next;
h->next=_n;
}

static void free_node( node_p _n)//释放结点
{
if(_n)
{
free(_n);
}
}

int isEmpty( node_p h)//判断链表是否为空
{
return h->next==NULL?1:0;
}

void popFront(node_p h,int *out)//从链表头部删除元素
{
if(!isEmpty(h))
{
node_p _n=h->next;
h->next=_n->next;
*out=_n->data;
free_node( _n);
}
}

void showList( node_p h)//打印链表
{
node_p start=h->next;
while(start)
{
printf(“%d “,start->data);
start=start->next;
}
printf(”\n”);
}

void destroyList( node_p h)//销毁链表
{
int out;
while(!isEmpty(h))
{
popFront(h,&out);
}
free_node(h);
}
void *product(void *arg)//生产者
{

 while(1)
 {
    int data=rand()%1234;//产生随机数
    pthread_mutex_lock(&lock);//加锁
    pushFront(head,data);//将产生的随机数头插到链表中(相当于生产)
    pthread_mutex_unlock(&lock);//解锁
    pthread_cond_signal(&cond);//生产完后唤醒消费者
    printf("The product success:%d\n",data);
    sleep(1);//1s生产一个
 }

}
void *consume(void *arg)//消费者
{
while(1)
{
int data=-1;//消费失败则输出-1
pthread_mutex_lock(&lock);
while(isEmpty(head))
{
printf(“no data,The consume wait…\n”);
pthread_cond_wait(&cond,&lock);//链表中无结点等待
}
popFront(head,&data);
pthread_mutex_unlock(&lock);
printf( “The consume success:%d\n”,data);
}
}
int main( )
{
pthread_t p;//定义p线程
pthread_t c;//定义c线程

pthread_create(&p,NULL,product,NULL);//创建线程
pthread_create(&c,NULL,consume,NULL);//创建线程

initList(&head);

destroyList(head);

pthread_join(p,NULL);//线程被等待
pthread_join(c,NULL);//线程被等待

return 0;

}


(3)运行成功可得到的结果是:


![这里写图片描述](https://img-blog.csdn.net/20170705160616148?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvWXlpbmdj/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)


上述就是关于基于单链表的生产者消费者模型,接下来我们来说说基于环形队列的生产者消费者模型。


什么是环形队列呢?如图所示


![这里写图片描述](https://img-blog.csdn.net/20170615104535000?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvWXlpbmdj/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)


每个格子就相当于超市的货架,当每个货架为空时,生产者才能生产,当每个货架有东西时,消费者才能消费,且生产者与消费者必须同步,且必须生产者快于消费者。


要符合环形队列的生产者消费者模型,生产者和消费者必须满足以下三个条件:   
 (1)生产者必须快于消费者   
 (2)生产者不能将消费者套圈   
 (3)消费者不能消费时,生产者先走。   
 生产者满时(不能在生产时),消费者先走。


要完成这一模型,我们必须还要了解一些关于Semaphore(信号量)的知识。


semaphore变量的类型为sem\_t。


初始化信号量   
 int sem\_init(sem\_t \*sem, int pshared, unsigned int value);   
 value参数表.示可用资源的数量,pshared参数为0表示信号量用于同一进程的线程。


在用完semaphore变量之后应该调用sem\_destroy()释放与semaphore相关的资源。   
 调用sem\_wait()可以获得资源(P操作),使semaphore的值减1,如果调用sem\_wait()时semaphore的值已经是0,则挂起等待。如果不希望挂起等待,可以调用sem\_trywait() 。   
 调用sem\_post() 可以释放资源(V操作),使semaphore 的值加1,同时唤醒挂起等待的线程。


生产者关心的是货架是否为空(格子是否空)所以生产者的大致做法是:   
 对空位数减1,放入数据,然后格子中含有数据的个数就加1。


消费者关心的是数据是否为空,所以消费者的大致做法是:对格子中含有数据的个数减1,拿出数据,然后空格子数加1。


在了解如上知识后,我们来看看基于环形队列的生产者消费者模型的相关代码吧!


(1)创建Makefile



ring:ring.c
gcc -o $@ $^ -lpthread
.PHONY:clean
clean:
rm -f ring


(2)创建ring.c



#include<stdio.h>
#include<pthread.h>
#include<semaphore.h>
#define SIZE 64
int ring[SIZE];//创建数组,存放数据

sem_t blank_sem;//定义信号量,表示空格子量
sem_t data_sem;//定义信号量,表示格子中含有数据的个数

void *product( void *arg)//生产者
{
int data=0;
int step=0;
while(1)
{
int data =rand( )%1234;
sem_wait(&blank_sem);//空格子减1
ring[step]=data;// 放入数据
sem_post(&data_sem);//格子中含有数据的个数加1
printf(“The product done:%d\n”,data);
step++;
step%=SIZE;
sleep(1);
}
}
void *consume( void *arg)
{
int step=0;
while(1)
{
int data=-1;//消费失败就会输出-1
sem_wait(&data_sem);//格子中含有数据的个数减1
data=ring[step];//拿出数据
sem_post(&blank_sem);//空格子数加1
printf(“The consume done:%d\n”,data);

   step++;
   step%=SIZE;

}

}
int main( )
{
pthread_t p;
pthread_t c;

pthread_create(&p,NULL,product,NULL);
pthread_create(&c,NULL,consume,NULL);

sem_init(&blank_sem,0,SIZE);//初始化信号量,刚开始的空格子数为SIZE大小
sem_init(&data_sem,0,0);//初始化信号量,刚开始的格子中含有数据的个数为0

pthread_join(p,NULL);
pthread_join(c,NULL);

sem_destroy(&blank_sem);//销毁信号量
sem_destroy(&data_sem);

return 0;
}


(3)运行成功后,就可以看到如图结果


![这里写图片描述](https://img-blog.csdn.net/20170615114405455?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvWXlpbmdj/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)


以上是基于环形队列的单生产者单消费者模型,接下来我们来看看基于环形队列的多生产者多消费者模型。


基于环形队列的多生产者多消费者模型是在单生产者单消费者模型的基础上增加了消费者与生产者。要实现这一个模型我们只需加入互斥锁实现生产者与生产者之间的互斥,消费者与消费者之间的互斥。具体代码如下(以三消费者,三生产者为例):



#include<stdio.h>
#include<pthread.h>
#include<semaphore.h>

#define SIZE 64
#define CONSUMER 3//定义生产者的个数
#define PRODUCTER 3//定义消费者的个数

int ring[SIZE];

pthread_mutex_t lock1= PTHREAD_MUTEX_INITIALIZER;//用于完成生产者与生产者之间的互斥
pthread_mutex_t lock2= PTHREAD_MUTEX_INITIALIZER;//用于完成消费者与消费者之间的互斥

sem_t blank_sem;
sem_t data_sem;

void *product( void *arg)
{
int data=0;
static int step=0;
while(1)
{
pthread_mutex_lock(&lock1);//加锁
int data =rand( )%1234;
sem_wait(&blank_sem);//p操作
ring[step]=data;//产生数据
sem_post(&data_sem);//v操作
printf(“The product done:%d\n”,data);
step++;
step%=SIZE;
pthread_mutex_unlock(&lock1);//解锁
sleep(2);

}

}
void *consume( void *arg)
{
static int step=0;
while(1)
{
pthread_mutex_lock(&lock2);//加锁
int data=-1;
sem_wait(&data_sem);
data=ring[step];
sem_post(&blank_sem);
printf(“The consume done:%d\n”,data);
step++;
step%=SIZE;
pthread_mutex_unlock(&lock2);//解锁
sleep(2);
}

}
int main( )
{
pthread_t p[PRODUCTER];//创建生产者数组
pthread_t c[CONSUMER];//创建消费者数组

int i=0;

img
img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上C C++开发知识点,真正体系化!

由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新

如果你需要这些资料,可以戳这里获取

[CONSUMER];//创建消费者数组

int i=0;

[外链图片转存中…(img-uW0hU5vB-1715802887303)]
[外链图片转存中…(img-9GQ96JNE-1715802887303)]

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上C C++开发知识点,真正体系化!

由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新

如果你需要这些资料,可以戳这里获取

  • 20
    点赞
  • 29
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值