Linux-生产者与消费者模型

文章目录

  • 一、什么是生产者与消费者模型?
  • 二、示例模型
    • 示例模型介绍
    • 交易场所(blockQueue)
    • 消费者与生产者
    • 运行结果
  • 总结


一、什么是生产者与消费者模型?

参照日常生活中,购买商品的人群可以被称之为消费者,生产商品的工厂可以被称之为生产者,而在两者之间还存在超市被称之为交易场所。 它们还存在三种关系,生产者与生产者之间是互斥关系,消费者与消费者之间也是互斥关系,消费者与生产者存在互斥/同步关系。这三种关系在多线程有着重要体现,通过我们之前所学习的互斥锁和条件变量可以反映这三种关系。

今天我们就需要用我们的多线程知识来构建一个简单的生产者与消费者模型。

二、示例模型

示例模型介绍

该模型由生产者线程随机生成(生产)两个随机数,消费者线程来进行对两个随机数进行计算(消费), 而我们的交易场所就由队列(queue)来充当。

生产者不断往队列放数据,消费者不断从队列拿数据,但是队列总有满/空的时候,所以我们就要严格控制他们的互斥/同步!

交易场所(blockQueue)

	blockQueue.hpp
#pragma once
#include <iostream>
#include <cstdio>
#include <unistd.h>
#include <pthread.h>
#include <queue>
#include "Task.hpp"
#include "lockGuard.hpp"
const int df_cap = 5;

template <class Data>
class blockQueue
{
public:
    blockQueue(int capacity = df_cap)
        : _capacity(capacity)
    {
   		//初始化
        pthread_cond_init(&_empty, nullptr);
        pthread_cond_init(&_full, nullptr);
        pthread_mutex_init(&_mutex, nullptr);
    }

    bool isEmpty()
    {
        return _queue.size() == 0;
    }

    bool isFull()
    {
        return _queue.size() == _capacity;
    }

    void push(const Data &data)
    {
        pthread_mutex_lock(&_mutex);
        while (isFull()) //由于pthread_cond_wait函数存在申请锁失败的情况,所以我们要使用while循环检查队列是否为满
            pthread_cond_wait(&_full, &_mutex);
        _queue.push(data);
        pthread_cond_signal(&_empty);
        pthread_mutex_unlock(&_mutex);
    }

    void pop(Data *output)
    {
        pthread_mutex_lock(&_mutex);
        while (isEmpty())//由于pthread_cond_wait函数存在申请锁失败的情况,所以我们要使用while循环检查队列是否为空
            pthread_cond_wait(&_empty, &_mutex);
        *output = _queue.front();
        _queue.pop();
        pthread_cond_signal(&_full);
        pthread_mutex_unlock(&_mutex);
    }

    ~blockQueue()
    {
        pthread_cond_destroy(&_empty);
        pthread_cond_destroy(&_full);
        pthread_mutex_destroy(&_mutex);
    }

private:
    std::queue<Data> _queue;
    int _capacity;
    pthread_cond_t _empty;
    pthread_cond_t _full;
    pthread_mutex_t _mutex;
};

该blockQueue主要是对队列进行一个封装,因为STL提供的容器一般都不是线程安全的,所以需要自己进行封装使它成为一个可重入的类型。

	Task.hpp
#pragma once
#include <iostream>
#include <functional>

class Task
{
public:
    typedef std::function<int(int, int)> func_t;

    Task() {}

    Task(int x, int y, func_t func)
        : _func(func), _x(x), _y(y)
    {
    }

    int operator()()
    {
        return _func(_x, _y);
    }

    int getelement1()
    {
        return _x;
    }

    int getelement2()
    {
        return _y;
    }

private:
    int _x;
    int _y;
    func_t _func;
};

消费者与生产者

#include "blockQueue.hpp"
#include <ctime>

#define P_TNUM 1
#define C_TNUM 5

void *consumer(void *args)
{
    blockQueue<Task> *queue = (blockQueue<Task> *)args;
    while (1)
    {
        // sleep(1);
        Task tmp;
        queue->pop(&tmp);
        std::cout << pthread_self() << "获取结果: " << tmp.getelement1() << " + " << tmp.getelement2() << " = " << tmp() << std::endl;
    }
    return nullptr;
}

void *productor(void *args)
{
    blockQueue<Task> *queue = (blockQueue<Task> *)args;

    while (1)
    {
        int x = rand() % 100 + 1;
        usleep(1000);
        int y = rand() % 10 + 1;
        Task task(x, y, [](const int x, const int y) -> int
                  { return x + y; }); //lambda表达式
        queue->push(task);
        std::cout << pthread_self() << "生产数据: " << task.getelement1() << " + " << task.getelement2() << " = ? " << std::endl;
        sleep(1);
    }
    return nullptr;
}

int main()
{
    srand((unsigned int)time(nullptr) ^ 0xfffffff ^ 0x12345678);

    pthread_t parr[P_TNUM], carr[C_TNUM];
    blockQueue<Task> *queue = new blockQueue<Task>;

    for (int i = 0; i < P_TNUM; i++)
    {
        pthread_create(parr + i, nullptr, productor, (void *)queue);
    }

    sleep(1);

    for (int i = 0; i < C_TNUM; i++)
    {
        pthread_create(carr + i, nullptr, consumer, (void *)queue);
    }

    for (int i = 0; i < P_TNUM; i++)
    {
        pthread_join(parr[i], nullptr);
    }

    for (int i = 0; i < C_TNUM; i++)
    {
        pthread_join(carr[i], nullptr);
    }

    delete queue;

    return 0;
}

运行结果

在这里插入图片描述


总结

本章主要检验自身多线程学习的成果,灵活运用了线程互斥和条件变量的接口函数,大家下来可以自己尝试写一遍。

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

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

相关文章

如果搭建axb回拨

AXB回拨技术是一种先进的电话通讯技术&#xff0c;它通过在A&#xff08;主叫方&#xff09;与B&#xff08;被叫方&#xff09;之间引入一个中间号码X&#xff0c;实现了双方的通话连接。这种技术可以有效避免直接拨打被叫方的电话号码&#xff0c;从而保护了用户的隐私。 具体…

《优化接口设计的思路》系列:第九篇—用好缓存,让你的接口速度飞起来

一、前言 大家好&#xff01;我是sum墨&#xff0c;一个一线的底层码农&#xff0c;平时喜欢研究和思考一些技术相关的问题并整理成文&#xff0c;限于本人水平&#xff0c;如果文章和代码有表述不当之处&#xff0c;还请不吝赐教。 作为一名从业已达六年的老码农&#xff0c…

学习笔记Day14:Linux下软件安装

软件安装 Anaconda 所有语言的包(package)、依赖(dependency)和环境(environment)管理器&#xff0c;类似应用商店 Conda < Miniconda < Anaconda&#xff08;有交互界面&#xff09; Linux下Miniconda即可 安装Miniconda 搜索北外/清华miniconda镜像网站&#xff…

使用专属浏览器在国内直连GPT教程

Wildcard官方推特发文说他们最近推出了一款专门为访问OpenAI设计的浏览器。 根据官方消息&#xff0c;这是一款专门为访问OpenAI优选网络设计的浏览器&#xff0c;它通过为用户提供专用的家庭网络出口&#xff0c;确保了快速、稳定的连接。 用这个浏览器的最大好处就是直接用浏…

【前端寻宝之路】学习和总结HTML的标签属性

&#x1f308;个人主页: Aileen_0v0 &#x1f525;热门专栏: 华为鸿蒙系统学习|计算机网络|数据结构与算法|MySQL| ​&#x1f4ab;个人格言:“没有罗马,那就自己创造罗马~” #mermaid-svg-tgsZb9zTBxJHHYhD {font-family:"trebuchet ms",verdana,arial,sans-serif;f…

蓝桥杯 2022 省B 李白打酒加强版

这题用递归暴力的方法如下&#xff1a; #include<iostream> #include<bits/stdc.h> using namespace std; int num; int N,M; void dfs(int now,int n,int m) {if(now<0 || n>N ||m>M)return ;if(nN && mM){if(now1)num1;return;}dfs(now-1,n,m1…

(一)、Doris安装使用(基于Doris 2.0.6)

第 1 章Doris简介 1.1、 Doris 概述 ​ Apache Doris由百度大数据部研发&#xff08;之前叫百度 Palo&#xff0c;2018年贡献到 Apache 社区后&#xff0c;更名为 Doris&#xff09;&#xff0c;在百度内部&#xff0c;有超过200个产品线在使用&#xff0c;部署机器超过1000台…

【力扣白嫖日记】613.直线上的最近距离

前言 练习sql语句&#xff0c;所有题目来自于力扣&#xff08;https://leetcode.cn/problemset/database/&#xff09;的免费数据库练习题。 今日题目&#xff1a; 613.直线上的最近距离 表&#xff1a;Point 列名类型xint 在SQL中&#xff0c;x是该表的主键列。该表的每一…

Redis 不再“开源”,对中国的影响及应对方案

Redis 不再“开源”&#xff0c;使用双许可证 3 月 20 号&#xff0c;Redis 的 CEO Rowan Trollope 在官网上宣布了《Redis 采用双源许可证》的消息。他表示&#xff0c;今后 Redis 的所有新版本都将使用开源代码可用的许可证&#xff0c;不再使用 BSD 协议&#xff0c;而是采用…

linux sh脚本编写

linux中bash Shell 是 Linux 的核心部分&#xff0c;它允许你使用各种诸如 cd、ls、cat 等的命令与 Linux 内核进行交互。Bash脚本和Shell脚本实际上是指同一种类型的脚本&#xff0c;只不过Bash是其中最常用的一种Shell。除了Bash之外&#xff0c;常见的Shell解释器还有C She…

【Django框架学习笔记】超详细的Python后端开发Django框架学习笔记

十二&#xff0c;Django框架 可以以下链接获取Django框架学习笔记,md文档和pdf文档 Django框架超详细的学习笔记&#xff0c;点击我获取 12.1 命令行操作 # 创建django项目 django-admin startproject aini# 启动项目 cd /mysite python3 manage.py runserver## 创建应用 …

BUUCTF---WEEK3(Rabin‘s RSA)

题目&#xff1a; from Crypto.Util.number import * from secret import flag p getPrime(64) q getPrime(64) assert p % 4 3 assert q % 4 3n p * qe 2 m bytes_to_long(flag)c pow(m,e,n)print(n , n) print(c , c)# n 201354090531918389422241515534761536573 …

MySQL面试题--事务

目录 1.什么是数据库事务&#xff1f;事务的特性是什么&#xff1f; 2.什么是ACID&#xff1f; 3.并发事务会有哪些问题&#xff1f; 4.什么是 脏读、丢失修改、不可重复读、幻读 5.不可重复读和幻读有什么区别&#xff1f; 6.Mysql是如何避免事务并发问题的&#xff1f; …

加一——大数据的应用

题目链接&#xff1a;66. 加一 - 力扣&#xff08;LeetCode&#xff09; 解题思路&#xff1a; 先将输入的数组转换成整数&#xff0c;对整数进行加一操作&#xff0c;然后再转换回数组&#xff0c;这样就不用考虑加一进位和数位增加的问题&#xff0c;很简单的思路但是运行时间…

操作简单的城市内涝一维二维耦合模拟软件

原文链接&#xff1a;最简单的城市内涝一维二维耦合模拟软件https://mp.weixin.qq.com/s?__bizMzUzNTczMDMxMg&mid2247598401&idx3&sn0c4c86b3a5d09a75b8f07e6fad81aa9c&chksmfa8200a6cdf589b0970a6854869e8e3a9f132fe40a19977863c091cbcf6d9786f067e0c5651e&…

UE5 GameMode C++函数 学习

已经尝试&#xff0c;确实能重启游戏 类描述符加了noplaceable过后即使是Actor也不能放到场景中了&#xff0c;关卡蓝图&#xff0c;GameMode&#xff0c;GameState这些就不能放场景中了 UFUNCTION(exec)

【Python + Django】表结构创建

以员工管理系统为例。 事前呢&#xff0c;我们先把项目和app创建出来&#xff0c;详细步骤可以看我同栏目的第一篇、第二篇文章。 我知道你们是不会下来找的&#xff0c;就把链接贴在下面吧&#xff1a; 【Python Django】启动简单的文本页面-CSDN博客 【Python Django】…

优维全面可观测产品能力分解⑥:运维状态可观测

本文是《优维全面可观测产品能力分解》系列文章的第六篇&#xff1a;『运维状态可观测』。基于可观测的数据体系&#xff0c;「运维状态可观测」是实现于运维状态的一次深入可观测。 在日常运维场景中&#xff0c;系统/应用运维人员重点关注的是系统/应用是否可用&#xff0c;…

大数据开发扩展shell--尚硅谷shell笔记

大数据开发扩展shell 学习目标 1 熟悉shell脚本的原理和使用 2 熟悉shell的编程语法 第一节 Shell概述 1&#xff09;Linux提供的Shell解析器有&#xff1a; [atguiguhadoop101 ~]$ cat /etc/shells /bin/sh/bin/bash/sbin/nologin/bin/dash/bin/tcsh/bin/csh2&#xff09…

男性三十三岁,头晕头疼,心慌和后背发紧,竟被它治好了!

植物神经紊乱是一种影响现代人健康的常见问题&#xff0c;它源于植物神经系统功能失调&#xff0c;导致身心健康出现一系列不适症状。植物神经紊乱对身体健康的影响是多方面的&#xff0c;它可能导致睡眠问题、情绪波动和自律神经功能紊乱等多种不适症状&#xff0c;严重影响个…