Linux--生產消費模型

線程系列:
Linux–線程的認識(一)
Linux–線程的分離、線程庫的地址關系的理解、線程的簡單封裝(二)
線程的互斥:臨界資源只能在同一時間被一個線程使用

生產消費模型

生產消費模型是多線程編程和分布式系統中的一個經典概念,它描述了生產者和消費者之間的交互方式。在這個模型中,生產者負責生成數據或任務,而消費者則負責處理這些數據或任務。這種模型在處理并發和異步操作時非常有用,尤其是在需要平衡生產速率和消費速率的情況下。

基本概念

生產者(Producer):負責生成數據或任務的實體。在多線程環境中,這通常是一個線程或一組線程。
消費者(Consumer):負責處理數據或任務的實體。同樣,這也可以是一個線程或一組線程。
緩沖區(Buffer):生產者和消費者之間的中間存儲區域,用于臨時存放生產者生成的數據,直到消費者準備好處理它們。

工作原理

  • 生產者:當生產者生成數據時,它將數據放入緩沖區。如果緩沖區已滿,生產者可能需要等待或停止生產,直到緩沖區有足夠的空間。
  • 消費者:消費者從緩沖區取出數據進行處理。如果緩沖區為空,消費者可能需要等待或暫停,直到有新的數據可用。

關鍵技術

  • 同步機制:如信號量、互斥鎖、條件變量等,用于控制對共享資源的訪問,確保生產者和消費者不會同時訪問或修改緩沖區。
  • 阻塞隊列:一種特殊的隊列,當嘗試添加或移除元素時,如果隊列已滿或為空,操作會被阻塞,直到條件滿足。

應用場景

  • 并發編程:在多線程環境中,生產消費模型可以幫助有效地管理資源和任務分配。
  • 分布式系統:在網絡服務中,如消息隊列系統,生產者可以是發送消息的服務,消費者則是接收并處理這些消息的服務。

生產消費模型是理解和實現高效并發和分布式系統的關鍵,通過合理設計和優化,可以顯著提高系統的性能和穩定性

單生產-單消費

BlockQueue.hpp: 阻塞隊列
阻塞隊列是一種支持兩個附加操作的隊列。這兩個附加的操作是:當隊列為空時,獲取元素的線程會等待隊列變為非空;當隊列已滿時,存儲元素的線程會等待隊列可用。

#ifndef __BLOCK_QUEUE_HPP__
#define __BLOCK_QUEUE_HPP__#include <iostream>
#include <string>
#include <queue>
#include <pthread.h>
using namespace std;template <class T>
class BlockQueue 
{
public:BlockQueue(int cap) :_cap(cap),_product_wait_num(0),_consum_wait_num(0){pthread_mutex_init(&_mutex,nullptr);pthread_cond_init(&_product_cond,nullptr);pthread_cond_init(&_consum_cond,nullptr);}void Enqueue(T& in)//生產者所用接口{pthread_mutex_lock(&_mutex);//對臨界資源開啟保護while(IsFull())//當隊列存滿后需要讓生產者停止生產,進入阻塞狀態{_product_wait_num++;pthread_cond_wait(&_product_cond,&_mutex);_product_wait_num--;}//開始生產_block_queue.push(move(in));//讓消費者來消費if(_consum_wait_num>0)pthread_cond_signal(&_consum_cond);pthread_mutex_unlock(&_mutex);}void Pop(T* out){pthread_mutex_lock(&_mutex);//對臨界資源開啟保護while(IsEmpty())//當隊列空缺后需要讓消費者停止消費,進入阻塞狀態{_consum_wait_num++;pthread_cond_wait(&_consum_cond,&_mutex);_consum_wait_num--;}//進行消費*out=_block_queue.front();_block_queue.pop();//通知生產者if(_product_wait_num>0)pthread_cond_signal(&_product_cond);pthread_mutex_unlock(&_mutex);}~BlockQueue(){pthread_mutex_destroy(&_mutex);pthread_cond_destroy(&_product_cond);pthread_cond_destroy(&_consum_cond);}
private:bool IsFull(){return _block_queue.size() == _cap;}bool IsEmpty(){return _block_queue.empty();}queue<T> _block_queue;//阻塞隊列int _cap; //總上限pthread_mutex_t _mutex; //互斥鎖pthread_cond_t _product_cond; //生產者的條件變量pthread_cond_t _consum_cond; //消費者的條件變量int _product_wait_num;int _consum_wait_num;
};
#endif

代碼解釋:

在這里插入圖片描述
在這里插入圖片描述
在這里插入圖片描述
main.cc: 主函數
在這里插入圖片描述

#include"BlockQueue.hpp"
#include"Thread.hpp"
#include<string>
#include<vector>
#include<unistd.h>using namespace ThreadMdule;
int a=10;
//生產者
void Productor(BlockQueue<int>& bq)
{int cnt=1;while (true){bq.Enqueue(cnt);std::cout << "Productor product data is : " << cnt << " addr: " << &bq << std::endl;cnt++;//sleep(3);}
}
//消費者
void Consumer(BlockQueue<int>& bq)
{while (true){int data;bq.Pop(&data);std::cout << "Consumer Consum data is : " << data << " addr: " << &bq << std::endl;sleep(5);}
}
//執行創建線程的函數
void StartComm(std::vector<Thread<BlockQueue<int>>> *threads, int num, BlockQueue<int> &bq, func_t<BlockQueue<int>> func)
{for (int i = 0; i < num; i++){std::string name = "thread-" + std::to_string(i + 1);//將線程放入threads中,記錄信息threads->emplace_back(func, bq, name);threads->back().start();}
}
void StartProductor(vector<Thread<BlockQueue<int>>>* threads,int num,BlockQueue<int>& bq)
{StartComm(threads,num,bq,Productor);
}
void StartConsumer(vector<Thread<BlockQueue<int>>>* threads,int num,BlockQueue<int>& bq)
{StartComm(threads,num,bq,Consumer);
}void WaitAllThread(std::vector<Thread<BlockQueue<int>>> &threads)
{for (auto &thread : threads){thread.Join();}
}
int main()
{BlockQueue<int>* bq=new BlockQueue<int>(5);vector<Thread<BlockQueue<int>>> threads;//用threads來記錄線程的信息StartProductor(&threads,1,*bq);StartConsumer(&threads,1,*bq);WaitAllThread(threads);
}

在這里插入圖片描述
在這里插入圖片描述

細節:

在這里插入圖片描述
在這里插入圖片描述

多生產-單消費

這里在上面主函數代碼上更改生產者的數量即可。

直接驗證:
在這里插入圖片描述

這里用任務類來作為阻塞隊列的任務,讓生產者產出對應任務,消費者來解決任務;生產出來的任務先放入阻塞隊列作為緩沖;

#include<iostream>
#include<string>
#include<functional>
using namespace std;class Task
{
public:Task(){}Task(int a,int b): _a(a),_b(b),_result(0){}void Excute(){_result=_a+_b;}string ResultToString(){return to_string(_a) + "+"+to_string(_b)+"="+to_string(_result);}string DebugToString(){return to_string(_a) + "+" + to_string(_b) + "= ?";}
private:int _a;int _b;int _result;
};

//類型
在這里插入圖片描述
//生產者:
在這里插入圖片描述
//消費者:
在這里插入圖片描述

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/44229.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/44229.shtml
英文地址,請注明出處:http://en.pswp.cn/web/44229.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

我們水冷使制動電阻功率密度成倍增加-水冷電阻設計工廠

先進陶瓷 我們后來發現工業應用中對占用空間最小的水冷電阻器的工業需求&#xff0c;推出了適用于中壓工業應用的水冷電阻器。它的特點是兩塊由具有特殊性能的先進陶瓷制成的板。 使用工業電驅動裝置的一個重要好處是&#xff0c;可靠的再生和動態制動系統可以補充或取代傳統…

Llama2 訓練指南

Llama2 是一個基于 Python 的機器學習框架&#xff0c;旨在幫助開發者快速構建和部署機器學習模型。下面是 Llama2 訓練指南&#xff0c;旨在幫助您了解如何使用 Llama2 訓練模型。 概述 Llama2 提供了多種方式來訓練模型&#xff0c;包括使用 Keras 和 TensorFlow。下面是在…

Laravel :如何將Excel文件導入數據庫

文章目錄 一、前提二、使用2.1、新建一個導入文件2.2、新建一個控制器和方法,調用導入文件2.3、 新建一個頁面&#xff0c;支持文件上傳 一、前提 想要將excel內容入庫&#xff0c;laravel有擴展可以使用,常用的擴展是maatwebsite/excel&#xff0c;安裝步驟參考上一篇&#x…

力扣 202快樂數

快樂數這題有兩個關鍵 一個是求n的 各個位上平方和 另一個是判斷是否為快樂數的依據是是否在哈希表中找到已經出現過的數 1求各個位上平方和方法 定義sum sum N除以十取余的平方和 n/10 循環終止條件是n0 2查找一個數是否出現&#xff0c;用哈希表unordered_set &…

Mosh|SQL教程第四彈(未完)

SQL有很多自帶的內聚的函數&#xff08;MAX、MIN、AVG、SUM、COUNT&#xff09; 一、聚合函數&#xff08;Aggregate Functions&#xff09; 這里的括號可以寫列名也可以寫表達式,下面是一個練習&#xff1a; 二、GROUP BY子句 統計2019-07-01以后每個客戶的總銷售額 注意這…

result.h

#ifndef ASYNCIO_RESULT_H #define ASYNCIO_RESULT_H#include <asyncio/exception.h> #include <variant> #include <optional> namespace ASYNCIO_NS {// 結果類封裝&#xff08;不是協程函數的返回類型&#xff09; template<typename T> struct Res…

Javaweb11-Filter過濾器

Filter過濾器 1.Filter的基本概念&#xff1a; 在Java Servlet中&#xff0c;Filter接口是用來處理HttpServletRequest和HttpServletResponse的對象的過濾器。主要用途是在請求到達Servlet之前或者響應離開Servlet之前對請求或響應進行預處理或后處理。 2.Filter常見的API F…

探展2024世界人工智能大會之合合信息掃描黑科技~

文章目錄 ?? 前言?? AIGC古籍修復文化遺產煥新?? 高效的文檔圖像處理解決方案?? AIGC掃描黑科技一鍵全搞定?? 行業級的大模型加速器?? 結語 ?? 前言 大家好&#xff0c;我是 哈哥&#xff08;哈哥撩編程&#xff09; &#xff0c;這次非常榮幸受邀作為專業觀眾參…

【常用知識點-Java】讀取Properties文件

Author&#xff1a;趙志乾 Date&#xff1a;2024-07-11 Declaration&#xff1a;All Right Reserved&#xff01;&#xff01;&#xff01; 1. 簡介 .properties文件是一種簡單的文本文件&#xff0c;用于存儲鍵值對&#xff0c;其每個鍵值對占一行&#xff0c;且鍵和值之間用…

力扣題解( 最長遞增子序列的個數)

673. 最長遞增子序列的個數 給定一個未排序的整數數組 nums &#xff0c; 返回最長遞增子序列的個數 。 注意 這個數列必須是 嚴格 遞增的。 思路&#xff1a; 用一個maxlen表示當前最長遞增數組的長度&#xff0c;maxcount表示最大長度。當進下標為i的元素時&#xff0c;將…

重磅!新公司法正式實施,這些變化你必須知道! ?

新公司法來了&#xff01;企業設立和經營必知的關鍵變動 &#x1f3db;?&#x1f680; 大家好&#xff0c;我是貓頭虎&#xff0c;科技自媒體博主。今天我們來聊聊一件大事——新公司法的實施&#xff0c;這對企業設立和經營帶來了哪些重大影響&#xff1f;跟著我&#xff0c…

【DDIM】DENOISING DIFFUSION IMPLICIT MODELS【論文精讀】【視頻講解】【公式推導】

論文&#xff1a;DENOISING DIFFUSION IMPLICIT MODELS&#xff08;https://arxiv.org/abs/2010.02502&#xff09; B站視頻鏈接 DDIM論文精講視頻 去噪擴散隱模型的論文精讀&#xff0c;涉及本文的大部分公式逐步推導。總計3小時的詳細論文講解。 講解詳細對應文檔 DDIM視頻…

聊聊mysql

記錄那些坑 本文會持續更新&#xff0c;陸續更新有關mysql技術內幕、實戰優化、面試技巧。 文章目錄 前言索引BTree之聚集索引BTree之輔助索引BTree之聯合索引BTree之覆蓋索引 使用到的工具1、py_innodb_page_info工具2、hexdump工具 總結 前言 重中之重的MySql數據庫 mysql…

模擬人機猜數游戲

設計目的 1、加深學生對該課程基礎知識和基本理論的理解和掌握&#xff0c;培養學生綜合運用所學知識獨立 分析和解決問題的能力; 2、培養學生在計算機軟硬件開發、理論計算、查閱資料等方面的能力&#xff0c;使學生逐步樹立正 確的設計思想; 3、加強理論聯系實際&#xff0c…

邦芒支招:職場高效溝通的6個秘訣

??俗話說得好“良言一句三冬暖&#xff0c;惡語傷人六月寒。”無論在什么單位&#xff0c;社會上竟是形形色色的人等&#xff0c;人過一百&#xff0c;形形色色。每個人都想得到他人賞識、揮灑才華、爭得提升。但是&#xff0c;要和陌生的人融洽相處、溝通合作&#xff0c;是…

Android 藍牙語音通話調試

首先要清楚藍牙語音通話屬于藍牙得哪一個協議 1、HEADSET 耳機和免提模式,用于藍牙耳機 2、A2DP (advanced audio distribution profile)高級音頻及立體聲規范,包括A2DP SINK和A2DP SOURCE 3、HEALTH 健康設備規范,和一些健康設備進行通信 4、OPP (object push profi…

概率論期末速成(知識點+例題)

考試范圍 一&#xff1a; 事件關系運算性質全概率公式、貝葉斯公式古典概型 二&#xff1a; 離散分布律連續密度函數性質 -> 解決三個問題&#xff08;求待定系數、求概率、求密度函數&#xff09;分布函數 -> 解決三個問題常用分布&#xff08;最后一節課的那幾個分…

手電筒的光能飛到宇宙盡頭嗎

如果我們打開手電筒向夜空照一秒再關掉&#xff0c;我們將會看到&#xff0c;在關掉手電筒的一瞬間&#xff0c;手電筒發出的光束也會消失&#xff0c;那么&#xff0c;它發出的光哪去了呢&#xff1f;下面我們就來聊一下這個話題。實際上&#xff0c;我們看到的光束&#xff0…

Spark SQL 概述

Spark SQL 概述 Spark SQL 是 Apache Spark 的一個模塊&#xff0c;專門用于處理結構化數據。它集成了 SQL 查詢和 Spark 編程的強大功能&#xff0c;使得處理大數據變得更加高效和簡便。通過 Spark SQL&#xff0c;用戶可以直接在 Spark 中使用 SQL 查詢&#xff0c;或者使用 …

ubuntu16.04安裝低版本cmake(安裝cmake安裝)

文章目錄 ubuntu16.04安裝低版本cmake&#xff08;安裝cmake安裝&#xff09;1. **下載并解壓CMake壓縮文件**&#xff1a;- 首先&#xff0c;你需要從CMake的官方網站或其他可靠來源下載cmake-2.8.9-Linux-i386.tar.gz文件。- 然后在終端中使用以下命令解壓文件&#xff1a; 2…