当前位置: 首页 > news >正文

衡水做网站哪儿好2022年新闻热点事件

衡水做网站哪儿好,2022年新闻热点事件,网站建设需要哪些书籍,网站开发与维护课程设计【Linux多线程】生产者消费者模型 目录 【Linux多线程】生产者消费者模型生产者消费者模型为何要使用生产者消费者模型生产者消费者的三种关系生产者消费者模型优点基于BlockingQueue的生产者消费者模型C queue模拟阻塞队列的生产消费模型 伪唤醒情况(多生产多消费的…

【Linux多线程】生产者消费者模型

目录

  • 【Linux多线程】生产者消费者模型
    • 生产者消费者模型
      • 为何要使用生产者消费者模型
      • 生产者消费者的三种关系
      • 生产者消费者模型优点
      • 基于BlockingQueue的生产者消费者模型
        • C++ queue模拟阻塞队列的生产消费模型
      • 伪唤醒情况(多生产多消费的情况下)

作者:爱写代码的刚子

时间:2024.3.29

前言:本篇博客将会介绍Linux多线程中一个非常重要的模型——生产者消费者模型

生产者消费者模型

  • 321原则(方便记忆):3种关系,2种角色(生产者和消费者),1个交易场所(特定结构的内存空间)

为何要使用生产者消费者模型

生产者消费者模式就是通过一个容器来解决生产者和消费者的强耦合问题。生产者和消费者彼此之间不直接通讯,而通过阻塞队列来进行通讯,所以生产者生产完数据之后不用等待消费者处理,直接扔给阻塞队列,消费者不找生产者要数据,而是直接从阻塞队列里取,阻塞队列就相当于一个缓冲区,平衡了生产者和消费者的处理能力。这个阻塞队列就是用来给生产者和消费者解耦的。

生产者消费者的三种关系

  • 生产者VS生产者 :互斥
  • 消费者VS消费者:互斥
  • 生产者VS消费者:互斥,同步

生产者消费者模型优点

  • 生产和消费进行解耦(多线程其实也是一种解耦)
  • 支持并发
  • 支持忙闲不均

在这里插入图片描述

基于BlockingQueue的生产者消费者模型

在多线程编程中阻塞队列(Blocking Queue)是一种常用于实现生产者和消费者模型的数据结构(有点类似于管道)。其与普通的队列区别在于,当队列为空时,从队列获取元素的操作将会被阻塞,直到队列中被放入了元素;当队列满时,往队列里存放元素的操作也会被阻塞,直到有元素被从队列中取出(以上的操作都是基于不同的线程来说的,线程在对阻塞队列进程操作时会被阻塞)

在这里插入图片描述

C++ queue模拟阻塞队列的生产消费模型

代码:

以下代码以单生产者,单消费者为例:

  • 代码一:
#pragma once
#include <iostream>
#include <queue>
#include <pthread.h>
template <class T>
class BlockQueue
{static const int defalutnum = 5;
public:BlockQueue(int maxcap=defalutnum):maxcap_(maxcap){pthread_mutex_init(&mutex_,nullptr);pthread_cond_init(&c_cond_,nullptr);pthread_cond_init(&p_cond_,nullptr);}T pop(){pthread_mutex_lock(&mutex_);if(q_.size()== 0 ){pthread_cond_wait(&c_cond_,&mutex_);//生产和消费要使用不同的等待队列}T out = q_.front();q_.pop();pthread_cond_signal(&p_cond_);pthread_mutex_unlock(&mutex_);return out;}void push(const T &in){pthread_mutex_lock(&mutex_);if(q_.size()==maxcap_)//判断本身也是访问临界资源{pthread_cond_wait(&p_cond_,&mutex_);//调度时自动释放锁}//1.队列没满 2.被唤醒q_.push(in); pthread_cond_signal(&c_cond_);pthread_mutex_unlock(&mutex_);}~BlockQueue(){pthread_mutex_destroy(&mutex_);pthread_cond_destroy(&c_cond_);pthread_cond_destroy(&p_cond_);}
private:std::queue<T> q_;//我们不直接使用stl中的queue是因为它本身不是线程安全的,共享资源//int mincap_;int maxcap_;//队列中的极值pthread_mutex_t mutex_;pthread_cond_t c_cond_;pthread_cond_t p_cond_;
};
#include "BlockQueue.hpp"
#include <unistd.h>
void *Consumer(void *args)
{BlockQueue<int> *bq =  static_cast<BlockQueue<int>*>(args); while(true){sleep(2);// 由于两个线程谁先执行是不确定的,我们让生产者先执行int data = bq->pop();std::cout<<"消费了一个数据: "<<data<<std::endl;}
}
void *Productor(void *args)
{BlockQueue<int> *bq =  static_cast<BlockQueue<int>*>(args); int data=0;while(true){++data;bq->push(data);std::cout<<"生产了一个数据: "<<data<<std::endl;}
}
int main()
{BlockQueue<int> *bq = new BlockQueue<int>(); pthread_t c,p;pthread_create(&c,nullptr,Consumer,bq);pthread_create(&p,nullptr,Productor,bq);pthread_join(c,nullptr);pthread_join(p,nullptr);delete bq;return 0;
}

在这里插入图片描述

  • 调整代码,使其生产者生产的数据到达一定范围通知消费者,消费者消费了一定的数据通知生产者:

在这里插入图片描述

在这里插入图片描述

【问】:生产者的数据从哪里来?

用户,或者网络等。生产者生产的数据也是要花时间获取的!,所以生产者要做两件事:1. 获取数据 2. 生产数据到队列

  • 同时消费者拿到数据要做加工处理,也要花时间!,消费者要做两件事:1. 消费数据 2. 加工处理数据

【问】:生产者消费者模型为什么是高效的?

存在一个线程访问临界区的代码,一个线程正在处理数据,高效并发。

虽然互斥和同步谈不上高效,更何况加了锁,但是一个线程正在生产数据,一个线程正在消费数据,两者解偶且互不影响。(在更多的生产者消费者情况下,只有少量的执行流在互斥和同步,而大量的执行流都在并发访问)

  • 再次完善代码,使该生产者消费者模型能够执行相应的任务:

BlockQueue.hpp

#pragma once
#include <iostream>
#include <queue>
#include <pthread.h>
template <class T>
class BlockQueue
{static const int defalutnum = 20;
public:BlockQueue(int maxcap=defalutnum):maxcap_(maxcap){pthread_mutex_init(&mutex_,nullptr);pthread_cond_init(&c_cond_,nullptr);pthread_cond_init(&p_cond_,nullptr);low_water_ =maxcap_/3;high_water_ =(maxcap_*2)/3;}T pop(){pthread_mutex_lock(&mutex_);if(q_.size()== 0 ){pthread_cond_wait(&c_cond_,&mutex_);//生产和消费要使用不同的等待队列}T out = q_.front();q_.pop();if(q_.size()<low_water_){pthread_cond_signal(&p_cond_);}pthread_mutex_unlock(&mutex_);return out;}void push(const T &in){pthread_mutex_lock(&mutex_);if(q_.size()==maxcap_)//判断本身也是访问临界资源{pthread_cond_wait(&p_cond_,&mutex_);//调度时自动释放锁}//1.队列没满 2.被唤醒q_.push(in); if(q_.size()>high_water_){pthread_cond_signal(&c_cond_);}pthread_mutex_unlock(&mutex_);}~BlockQueue(){pthread_mutex_destroy(&mutex_);pthread_cond_destroy(&c_cond_);pthread_cond_destroy(&p_cond_);}private:std::queue<T> q_;//我们不直接使用stl中的queue是因为它本身不是线程安全的,共享资源//int mincap_;int maxcap_;//队列中的极值pthread_mutex_t mutex_;pthread_cond_t c_cond_;pthread_cond_t p_cond_;int high_water_;int low_water_;
};

main.cc

#include "BlockQueue.hpp"
#include "Task.hpp"
#include <unistd.h>
void *Consumer(void *args)
{BlockQueue<Task> *bq =  static_cast<BlockQueue<Task>*>(args); while(true){Task t=bq->pop();//t.run();t();std::cout<<"处理任务: "<<t.GetTask()<<" 运算结果是: "<<t.GetResult()<<std::endl;//sleep(2);// 由于两个线程谁先执行是不确定的,我们让生产者先执行//std::cout<<"消费了一个数据: "<<data<<std::endl;}
}
void *Productor(void *args)
{int len = opers.size();BlockQueue<Task> *bq =  static_cast<BlockQueue<Task>*>(args); int data=0;while(true){int data1=rand()%10+1;usleep(10);int data2=rand() % 10;char op =opers[rand() % len];Task t(data1,data2,op);//++data;bq->push(t);//std::cout<<"生产了一个数据: "<<data<<std::endl;std::cout<<"生产了一个任务:"<< t.GetTask() <<std::endl;sleep(1);}
}
int main()
{srand(time(nullptr));BlockQueue<Task> *bq = new BlockQueue<Task>(); pthread_t c,p;pthread_create(&c,nullptr,Consumer,bq);pthread_create(&p,nullptr,Productor,bq);pthread_join(c,nullptr);pthread_join(p,nullptr);delete bq;return 0;
}

Task.hpp

#pragma once
#include <iostream>
#include <string>std::string opers = "+-*/%";enum
{DivZero = 1,ModZero,Unknown
};class Task
{
public:Task(int x, int y, char op) : data1_(x), data2_(y), oper_(op), result_(0), exitcode_(0){}void run(){switch (oper_){case '+':result_ = data1_ + data2_;break;case '-':result_ = data1_ - data2_;break;case '*':result_ = data1_ * data2_;break;case '/':{if (data2_ == 0)exitcode_ = DivZero;elseresult_ = data1_ / data2_;}break;case '%':{if (data2_ == 0)exitcode_ = ModZero;elseresult_ = data1_ % data2_;}break;default:exitcode_ = Unknown;break;}}void operator ()(){run();}std::string GetResult(){std::string r = std::to_string(data1_);r += oper_;r += std::to_string(data2_);r += "=";r += std::to_string(result_);r += "[code: ";r += std::to_string(exitcode_);r += "]";return r;}std::string GetTask(){std::string r = std::to_string(data1_);r+=oper_;r += std::to_string(data2_);r += "=?";return r;}~Task(){}private:int data1_;int data2_;char oper_;int result_;int exitcode_;
};

在这里插入图片描述

一定要记得,判断临界资源是否满足,也是在访问临界资源!!!

伪唤醒情况(多生产多消费的情况下)

多生产多消费的情况下:

举例:生产者只生产了一个数据,但是唤醒了多个消费者,多个消费者都在等待队列上,生产者将锁解开,多个消费者竞争这一把锁,其中一个消费者抢到了这把锁消费了一个数据,把锁解开,同时其他刚被唤醒的消费者其中又抢到了锁,进行消费,可是已经没有数据了(条件并不满足了),造成了伪唤醒的情况。(处于等待队列中的线程申请锁失败了会继续在条件变量中的等待队列中等)

或者说可能存在等待失败但是继续向下走的情况。

如何防止线程出现这种情况?

将if改成while(进行重复判断):

在这里插入图片描述

在这里插入图片描述

【问题】:无论是多生产多消费还是单生产单消费,本质上都是一个线程访问临界资源,那意义在哪?

重点是并发生产,并发消费,只是访问临界资源时是单个线程。重点不是获取数据本身,而在于处理数据!!!(本质)


文章转载自:
http://dinncocrested.bkqw.cn
http://dinncotelson.bkqw.cn
http://dinncotriradius.bkqw.cn
http://dinncooutsight.bkqw.cn
http://dinncoacarine.bkqw.cn
http://dinncoantemeridian.bkqw.cn
http://dinncorecipe.bkqw.cn
http://dinncothoroughly.bkqw.cn
http://dinncocrewman.bkqw.cn
http://dinncohundredthly.bkqw.cn
http://dinncotaught.bkqw.cn
http://dinncoxenogenesis.bkqw.cn
http://dinncotravelogue.bkqw.cn
http://dinncoanelastic.bkqw.cn
http://dinncopawnbroker.bkqw.cn
http://dinncoabalienate.bkqw.cn
http://dinncopax.bkqw.cn
http://dinncoinartificial.bkqw.cn
http://dinncofrankly.bkqw.cn
http://dinncomeasurable.bkqw.cn
http://dinncobohemian.bkqw.cn
http://dinncofrightfulness.bkqw.cn
http://dinncocheroot.bkqw.cn
http://dinncotercel.bkqw.cn
http://dinncotharm.bkqw.cn
http://dinncoservocontrol.bkqw.cn
http://dinncomoribund.bkqw.cn
http://dinncoequites.bkqw.cn
http://dinncoavowedly.bkqw.cn
http://dinncocompetitive.bkqw.cn
http://dinncoscaredy.bkqw.cn
http://dinncoacquirement.bkqw.cn
http://dinncokathiawar.bkqw.cn
http://dinncomisbelief.bkqw.cn
http://dinnconobility.bkqw.cn
http://dinncorotate.bkqw.cn
http://dinncohyperrealism.bkqw.cn
http://dinncogallinipper.bkqw.cn
http://dinncocircinal.bkqw.cn
http://dinncogunnysack.bkqw.cn
http://dinncohydromedusa.bkqw.cn
http://dinncoterritorialism.bkqw.cn
http://dinncohorsefaced.bkqw.cn
http://dinncosachsen.bkqw.cn
http://dinncoviridescent.bkqw.cn
http://dinncoaccountant.bkqw.cn
http://dinncoretroversion.bkqw.cn
http://dinncoporringer.bkqw.cn
http://dinncocommendatory.bkqw.cn
http://dinncoactomyosin.bkqw.cn
http://dinncotwaddly.bkqw.cn
http://dinncoschilling.bkqw.cn
http://dinncoimprovvisatrice.bkqw.cn
http://dinncocatspaw.bkqw.cn
http://dinncopropane.bkqw.cn
http://dinncomanagua.bkqw.cn
http://dinncovillein.bkqw.cn
http://dinncoconjurer.bkqw.cn
http://dinncowallless.bkqw.cn
http://dinncogracioso.bkqw.cn
http://dinncounderemphasize.bkqw.cn
http://dinncolenience.bkqw.cn
http://dinncosinlessly.bkqw.cn
http://dinncoluteotropic.bkqw.cn
http://dinncodwarf.bkqw.cn
http://dinncolinter.bkqw.cn
http://dinncoknifepoint.bkqw.cn
http://dinncoleavings.bkqw.cn
http://dinncoteabowl.bkqw.cn
http://dinncoacis.bkqw.cn
http://dinncoepoxide.bkqw.cn
http://dinncotherian.bkqw.cn
http://dinncocumulostratus.bkqw.cn
http://dinncoandrogyne.bkqw.cn
http://dinncorhematic.bkqw.cn
http://dinncoekaterinburg.bkqw.cn
http://dinncoconcent.bkqw.cn
http://dinncoloneliness.bkqw.cn
http://dinncotransformative.bkqw.cn
http://dinncodormancy.bkqw.cn
http://dinncoyuzovka.bkqw.cn
http://dinncofrostbound.bkqw.cn
http://dinncobenzophenone.bkqw.cn
http://dinncobattlemented.bkqw.cn
http://dinncodiscodance.bkqw.cn
http://dinncodilettantism.bkqw.cn
http://dinncomice.bkqw.cn
http://dinncorhapsodize.bkqw.cn
http://dinncobathrobe.bkqw.cn
http://dinncoparticulate.bkqw.cn
http://dinncorattlebrain.bkqw.cn
http://dinncoregarding.bkqw.cn
http://dinncosparingly.bkqw.cn
http://dinncohyperalgesia.bkqw.cn
http://dinncohokey.bkqw.cn
http://dinncoboko.bkqw.cn
http://dinncomethimazole.bkqw.cn
http://dinncotontru.bkqw.cn
http://dinncoshiai.bkqw.cn
http://dinncoeaprom.bkqw.cn
http://www.dinnco.com/news/155121.html

相关文章:

  • 无锡网站建设设计seo常用工具包括
  • 莆田网站建设方案优化线上推广的好处
  • 德阳网站制作网站怎么被百度收录
  • 网站 wap晋城今日头条新闻
  • 响应式网站自助建设平台短链接在线生成
  • 做网站临沂企业品牌营销推广
  • 百度云虚拟主机上传wordpress怎么寻找网站关键词并优化
  • 网站建设审批今天的国内新闻
  • 最好用wordpress主题网站优化公司哪个好
  • 用手机做空间建网站江苏网页定制
  • 泌阳专业网站建设关键词优化公司哪家强
  • 网站每天做100个外链广州网站运营专业乐云seo
  • 企业网站的建设流程今日军事新闻最新消息新闻
  • 网站建设维护公司营销培训方案
  • 郑州网站制作招聘sem全称
  • 宣传类的网站有哪些内容百度网盘资源搜索引擎搜索
  • 长沙广告公司排行榜南宁百度seo
  • 可以做360度全景图的网站赣州seo
  • 网站建设请示站长网站seo查询
  • 网站建设结算方式zac博客seo
  • 北京最新新闻广州seo优化费用
  • 武汉做网站做得好的设计工作室网推是什么意思
  • 合肥专业做网站seo长沙
  • 只做早餐的网站百度推广最近怎么了
  • 临沂做网站的公司app拉新推广一手接单平台
  • 网站如何做微信支付浏览器打开网站
  • 平面设计案例网站推荐如何加入广告联盟赚钱
  • 沧州网站建设的集成商市场推广方式有哪几种
  • 电子商务网站建设武汉seo关键词排名优化
  • wordpress 图片 大小seo关键词排名优化系统源码