生产消费者模型-环形队列与信号量

文章目录

  • 前言
  • 一、怎样的环形队列?
  • 二、什么是信号量
  • 三、使用步骤
    • 信号量的接口函数
      • 1. sem_init
      • 2.sem_destroy
      • 3.sem_wait
      • 4.sem_post
    • 环形队列的设计
    • 测试用例


前言

之前我们使用互斥锁和条件变量实现过一个生产者消费者模型,那么那个生产消费者模型具有一个缺点那就是只能串形生产与消费。

在某些环境与需求下,我们可以拥有比较大的数据空间,且我们的数据是批次分布在该空间中,我们是否可以让生产与消费并行呢?
通过环形队列我们其实是可以实现的,并且我们本次学习尝试学习认识和如何使用信号量。


一、怎样的环形队列?

这里我们通过例如vector的数组来模拟出环形队列,通过下标%vector.size(),就可以模拟出环形队列。
在这里插入图片描述

二、什么是信号量

信号量的本质其实就是一个计数器,他分别具有P操作和V操作,其中P操作可以简单的理解为计数器–,V操作可以简单的理解为计数器++。

而他最重要的就在于信号量的接口操作函数都是原子性的,是线程安全的。

在本次的生产消费者模型中,就充当着可用空间计数和有效数据计数。

三、使用步骤

信号量的接口函数

1. sem_init

在这里插入图片描述
该函数用于初始化信号量,其中参数pshared若为0,则不在线程之间共享,参数value则为信号量计数器的初始计数。

2.sem_destroy

在这里插入图片描述
销毁信号量。

3.sem_wait

在这里插入图片描述
代表着信号量的P操作,也就是让该信号量计数器–。

4.sem_post

在这里插入图片描述
代表着信号量的V操作,也就是让该信号量计数器++。

我们再把信号量进行包装一下

#include<semaphore.h>

class Sem{
public:
    Sem(unsigned int value)
    {
        sem_init(&_sem,0,value);
    }

    void p()
    {
        sem_wait(&_sem);
    }

    void v()
    {
        sem_post(&_sem);
    }
    ~Sem()
    {
        sem_destroy(&_sem);
    }
private:
    sem_t _sem;
};

环形队列的设计

#include<iostream>
#include<vector>
#include"semaphore.hpp"
#define DEFAULT_NUM 5 
template<class T>
class ringQueue{
    public:
    ringQueue(int default_num = DEFAULT_NUM)
    :_queue(default_num)
    ,c_step(0)
    ,p_step(0)
    ,data_sem(0)
    ,space_sem(default_num)
    {}

    void push(T& data)
    {
        space_sem.p();
        _queue[p_step++] = data;
        p_step %= _queue.size();
        data_sem.v();
    }

    void pop(T* data)
    {
        data_sem.p();
        *data = _queue[c_step++];
        c_step %= _queue.size();
        space_sem.v();
    }
    private:
    std::vector<T> _queue;
    int c_step;
    int p_step;
    Sem data_sem;
    Sem space_sem;
};

测试用例

#include"ringQueue.hpp"
#include<time.h>
#include<stdlib.h>
#include<unistd.h>
void* productor(void* args)
{
    ringQueue<int>* ring_queue = (ringQueue<int>*)args;
    while(1)
    {   
        int data = rand() % 100 + 1;
        ring_queue->push(data);
        std::cout << "生产者已生产数据: " << data << std::endl; 
        //sleep(1);
    }

}

void* consumer(void* args)
{
    ringQueue<int>* ring_queue = (ringQueue<int>*)args;
    while(1)
    {
        int data;
        ring_queue->pop(&data);
        std::cout << "消费者已消费数据: " << data << std::endl; 
        sleep(1);
    }
}



int main()
{
    srand((size_t)time(nullptr)^ getpid());
    ringQueue<int> ring;
    pthread_t p1;
    pthread_t p2;
    pthread_create(&p1,nullptr,productor,(void*)(&ring));
    pthread_create(&p2,nullptr,consumer,(void*)(&ring));
    

    pthread_join(p1,nullptr);
    pthread_join(p2,nullptr);
    return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/626932.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

YOLOv9改进策略 | 低照度图像篇 | 2024最新改进CPA-Enhancer链式思考网络(适用低照度、图像去雾、雨天、雪天)

一、本文介绍 本文给大家带来的2024.3月份最新改进机制&#xff0c;由CPA-Enhancer: Chain-of-Thought Prompted Adaptive Enhancer for Object Detection under Unknown Degradations论文提出的CPA-Enhancer链式思考网络&#xff0c;CPA-Enhancer通过引入链式思考提示机制&am…

Centos 6.10 安装oracle10.2.0.1

由于阿里云机房要下架旧服务器&#xff0c;单位未购买整机迁移服务&#xff0c;且业务较老不兼容Oracle11g&#xff0c;所以新购买一台新服务器进行安装Oracle10.2.0.1 &#xff0c;后续再将数据迁移到新服务器上。 对外ip 内部ip 数据库版本 操作系统版本 实例名 源库 1…

Pyqt中QThread传递自己定义的参数、类、函数

Pyqt中QThread传递自己定义的参数、类、函数 1 pyqt中Qthread传递自己定义的参数2 pyqt中Qthread传递自己定义的类3 pyqt中Qthread传递自己定义的函数4 pyqt中Qthread内部定义自己的函数5 pyqt中Qthread传递参数到内部定义自己的函数 1 pyqt中Qthread传递自己定义的参数 在PyQ…

Linux: Make工具以及Makefile文件

make工具 人们通常利用 make 工具来自动完成编译工作。这些工作包括&#xff1a;如果仅修改了某几个源文件&#xff0c;则只重新编译这几个源文件&#xff1b;如果某个头文件被修改了&#xff0c;则重新编译所有包含该头文件的源文件。利用这种自动编译可大大简化开发工作&…

Pytorch代码基础—张量

Pytorch代码—张量 Pytorch张量 张量的属性&#xff1a; data&#xff1a;被包装的Tensorgrad&#xff1a;data的梯度grad_fn:创建Tensor的Function&#xff0c;是自动求导的关键requires_grad&#xff1a;指示是否需要梯度isleaf&#xff1a;指示是否是叶子结点&#xff0…

第四课,python基础语法(算术运算符及其复合运算符、字符串三种定义方式)

一&#xff0c;算术运算符 经过前几节课的学习之后同学们对加减乘除已经不再陌生&#xff0c;本节课进一步掌握两个新的运算符&#xff0c;整除&#xff08;//&#xff09;和模&#xff08;%&#xff09;&#xff0c;整除用来计算两数相除的商&#xff0c;而模用来计算两数相除…

ES6之正则扩展

正则表达式扩展 u修饰符&#xff08;Unicode模式&#xff09;y修饰符&#xff08;Sticky或粘连模式&#xff09;s修饰符&#xff08;dotAll模式&#xff09;Unicode属性转义正则实例的flags属性字符串方法与正则表达式的整合 javascript的常用的正则表达式 验证数字邮箱验证手机…

windows 安装 Conda

1 Conda简介 Conda 是一个开源的软件包管理系统和环境管理系统&#xff0c;用于安装多个版本的软件包及其依赖关系&#xff0c;并在它们之间轻松切换。Conda 是为 Python 程序创建的&#xff0c;适用于 Linux&#xff0c;OS X 和Windows&#xff0c;也可以打包和分发其他软…

【LAMMPS学习】九、LAMMPS脚本 示例

9. 示例脚本 LAMMPS 发行版包含一个包含许多示例问题的示例子目录。许多是二维模型&#xff0c;运行速度快且易于可视化&#xff0c;在台式机上运行最多需要几分钟。每个问题都有一个输入脚本 (in.*)&#xff0c;并在运行时生成一个日志文件 (log.*)。有些使用初始坐标的数据文…

刷代码随想录有感(65):回溯算法——组合问题

题干&#xff1a; 代码&#xff1a; class Solution { public:vector<vector<int>> res;vector<int> tmp;void backtracking(int n, int k, int start){if(tmp.size() k){res.push_back(tmp);return;}for(int i start; i < n; i){tmp.push_back(i);bac…

支持不同业务模式与安全要求的跨网传输解决方案,了解一下

对于科技研发型企业来说&#xff0c;最值钱的是研发代码这类数据资产。因此很多企业会想将这些数据“困”在内部&#xff0c;防止数据泄露。最常见的做法是通过防火墙、DMZ区、双网卡主机、虚拟机、网闸/光闸等隔离方式&#xff0c;将网络划分为企业内外网&#xff0c;较为常见…

云商城系统源码,无后门,一站式系统Java源码

云商城系统&#xff0c;无后门&#xff0c;一站式系统Java源码&#xff0c;心权益商品数量不限数量 系统对接 手动发货 自动发货 兑 换 码 订单监控 商品监控 对象存储 邮箱提醒 加价模板 密价功能 三方支付 会员体系 财务明细 交易分析 售后服务 技术支持 【Java源码】云商…

Java面试八股之为什么要使用克隆

Java中为什么要使用克隆&#xff1f;怎么实现对象的克隆&#xff1f;深拷贝和浅拷贝的区别是什么 在Java中使用克隆主要有以下几个原因&#xff1a; 创建对象副本&#xff1a;克隆可以快速创建一个与原对象状态完全相同的副本&#xff0c;无需手动逐一复制每个属性。这种情况…

04-单片机商业项目编程,从零搭建低功耗系统设计

一、本文内容 上一节《03-单片机商业项目编程&#xff0c;从零搭建低功耗系统设计-CSDN博客》我们确定了设计思路&#xff0c;并如何更有效的保持低功耗&#xff0c;这节我们就准备来做软件框架设计。在AI飞速发展的时代&#xff0c;我们也会利AI来辅助我们完成&#xff0c;让自…

k8s v1.20二进制部署 部署 CNI 网络组件 部署 Calico

一、部署 flannel 1.1.K8S 中 Pod 网络通信 ●Pod 内容器与容器之间的通信 在同一个 Pod 内的容器&#xff08;Pod 内的容器是不会跨宿主机的&#xff09;共享同一个网络命名空间&#xff0c;相当于它们在同一台机器上一样&#xff0c;可以用 localhost 地址访问彼此的端口。…

【MATLAB源码-第59期】基于matlab的QPSK,16QAM164QAM等调制方式误码率对比,调制解调函数均是手动实现未调用内置函数。

操作环境&#xff1a; MATLAB 2022a 1、算法描述 正交幅度调制&#xff08;QAM&#xff0c;Quadrature Amplitude Modulation&#xff09;是一种在两个正交载波上进行幅度调制的调制方式。这两个载波通常是相位差为90度&#xff08;π/2&#xff09;的正弦波&#xff0c;因此…

【R语言与统计】SEM结构方程、生物群落、多元统计分析、回归及混合效应模型、贝叶斯、极值统计学、meta分析、copula、分位数回归、文献计量学

统计模型的七大类&#xff1a;一&#xff1a;多元回归 在研究变量之间的相互影响关系模型时候&#xff0c;用到这类方法&#xff0c;具体地说&#xff1a;其可以定量地描述某一现象和某些因素之间的函数关系&#xff0c;将各变量的已知值带入回归方程可以求出因变量的估计值&…

[Algorithm][回溯][组合][目标和][组合总和]详细讲解

目录 1.组合1.题目链接2.算法原理详解3.代码实现 2.目标和1.题目链接2.算法原理详解3.代码实现 3.组合总和1.题目链接2.算法原理详解3.代码实现 1.组合 1.题目链接 组合 2.算法原理详解 思路&#xff1a;每次都只选一个数&#xff0c;此后只能选它后面的数函数设计&#xff…

RK3568平台开发系列讲解(SPI篇)spi_dev 驱动分析

🚀返回专栏总目录 文章目录 一、结构体二、API三、spidev驱动分析3.1、init3.2、probe3.3、spidev_write3.4、spidev_read3.5、spidev_open四、spi_register_driver分析五、spi_dev缺点沉淀、分享、成长

通过java将数据导出为PDF,包扣合并单元格操作

最近项目中需要将查询出来的表格数据以PDF形式导出&#xff0c;并且表格的形式包含横向行与纵向列的单元格合并操作&#xff0c;导出的最终效果如图所示&#xff1a; 首先引入操作依赖 <!--导出pdf所需包--><dependency><groupId>com.itextpdf</groupId&…