基于环形队列的生产消费模型【Linux】

基于环形队列的生产消费模型

在这里插入图片描述

pspace_sem_&&cdata_sem_

生产者关注的是环形队列当中是否有空间,只要有空间生产者就可以进行生产。
消费者关注的是环形队列当中是否有数据,只要有数据消费者就可以进行消费

用信号量来描述环形队列当中的空间资源(pspace_sem_)和数据资源(cdata_sem_),在我们初始信号量时给它们设置的初始值是不同的:

pspace_sem_的初始值设置为环形队列的容量,因为刚开始时环形队列当中全是空间。
cdata_sem_的初始值设置为0,因为刚开始时环形队列当中没有数据

生产者申请资源&&消费者释放资源

生产者每次生产数据前都需要先申请pspace_sem_:

  • pspace_sem_的值不为0,则信号量申请成功,此时生产者可以进行生产操作。
  • pspace_sem_的值为0,则信号量申请失败,此时生产者需要在pspace_sem_的等待队列下进行阻塞等待,直到环形队列当中有新的空间后再被唤醒

当生产者生产完数据后,应该释放cdata_sem_:

  • 生产者生产完数据,应该对cdata_sem_进行V操作
  • 生产者在生产数据前申请到的是pspace_sem_位置,当生产者生产完数据后,该位置当中存储的是生产者生产的数据,在该数据被消费者消费之前,该位置不再是空间位置,而应该是数据位置
  • 当生产者生产完数据后,意味着环形队列当中多了一个数据位置,因此我们应该对cdata_sem_进行V操作。

消费者每次消费数据前都需要先申请cdata_sem_:

  • cdata_sem_的值不为0,则信号量申请成功,此时消费者可以进行消费操作。
  • cdata_sem_的值为0,则信号量申请失败,此时消费者需要在cdata_sem_的等待队列下进行阻塞等待,直到环形队列当中有新的数据后再被唤醒

当消费者消费完数据后,应该释放pspace_sem_:

  • 消费者在进行消费前是对cdata_sem_进行的P操作,但是当消费者消费完数据,应该对pspace_sem_进行V操作
  • 消费者在消费数据前申请到的是数据位置,当消费者消费完数据后,该位置当中的数据已经被消费过了,再次被消费就没有意义了,为了让生产者后续可以在该位置生产新的数据,将该位置算作空间位置
  • 当消费者消费完数据后,意味着环形队列当中多了一个空间位置,因此我们应该对pspace_sem_进行V操作

在基于环形队列的生产者和消费者模型当中,生产者和消费者必须遵守以下几点

生产者和消费者在访问环形队列时

1、在环形队列为数据为空,或者数据满了 ,生产者和消费者会指向同一位置,如果在环形队列为数据为空,只能由生产者访问,如果在环形队列为数据数据满了,只能由消费者访问
在这里插入图片描述
2、环形队列中的数据不空和不满的时候,生产者和消费者一定指向不同的位置,生产者和消费者可以同时访问

在这里插入图片描述

3、生产者从消费者的位置开始一直按顺时针方向进行生产,如果生产者生产的速度比消费者消费的速度快,那么当生产者绕着消费者生产了一圈数据后再次遇到消费者,此时生产者就不应该再继续生产了,因为再生产就会覆盖还未被消费者消费的数据
4、消费者从生产者的位置开始一直按顺时针方向进行消费,如果消费者消费的速度比生产者生产的速度快,那么当消费者绕着生产者消费了一圈数据后再次遇到生产者,此时消费者就不应该再继续消费了,因为再消费就会消费到缓冲区中保存的废弃数据

POSIX信号量

信号量的本质描述临界资源中资源数目的计数器

信号量的PV操作:

P操作:我们将申请信号量称为P操作,申请信号量的本质就是申请获得临界资源中某块资源的使用权限,当申请成功时临界资源中资源的数目应该减一,因此P操作的本质就是让计数器减一。
V操作:我们将释放信号量称为V操作,释放信号量的本质就是归还临界资源中某块资源的使用权限,当释放成功时临界资源中资源的数目就应该加一,因此V操作的本质就是让计数器加一

信号量函数

sem_init,初始化信号量

int sem_init(sem_t *sem, int pshared, unsigned int value);

  • sem:需要初始化的信号量。
  • pshared:传入0值表示线程间共享,传入非零值表示进程间共享。
  • value:信号量的初始值(计数器的初始值)

return val :
初始化信号量成功返回0,失败返回-1

POSIX信号量和System V信号量作用相同,都是用于同步操作,达到无冲突的访问共享资源目的,但POSIX信号量可以用于线程间同步。

sem_destroy,销毁信号量

int sem_destroy(sem_t *sem);

  • sem:需要销毁的信号量。

return val :
销毁信号量成功返回0,失败返回-1

sem_wait,等待信号量

int sem_wait(sem_t *sem);

  • sem:需要等待的信号量

return val :
等待信号量成功返回0,信号量的值减一。
等待信号量失败返回-1,信号量的值保持不变

sem_post,发布信号量

int sem_post(sem_t *sem);

  • sem:需要发布的信号量

return val :
发布信号量成功返回0,信号量的值加一。
发布信号量失败返回-1,信号量的值保持不变

代码

单个生产者和单个消费者模型

多个生产者和多个消费者模型

线程池

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

鄃鳕

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值