linux--------------------BlockQueue的生產者消費模型

1.基礎BlockingQueue的生產者消費模型

1.1 BlockQueue

在多線程編程中阻塞隊列是一種常用于實現生產者和消費者模型的數據結構,它與普通的隊列區別在于,當隊列為空時,從隊列獲取元素的操作將被阻塞,直到隊列中放入了新的數據。當隊列滿的時候,往里面插入數據也會被阻塞直到有元素被取出

1.2 c++ queue模擬實現阻塞隊列的生產消費模型

為了理解我們來看一下代碼

#ifndef __BLOCK_QUEUE_HPP__
#define __BLOCK_QUEUE_HPP__
#include <iostream>
#include <string>
#include <queue>
#include <pthread.h>
template <typename T>
class BlockQueue
{
private:
bool IsFull()
{
return _block_queue.size() == _cap;
}
bool IsEmpty()
{
return _block_queue.empty();
}
public:
BlockQueue(int cap) : _cap(cap)
{
_productor_wait_num = 0;
_consumer_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()) // 保證代碼的健壯性
{
// ?產線程去等待,是在臨界區中休眠的!你現在還持有鎖呢!!!
// 1. pthread_cond_wait調?是: a. 讓調?線程等待 b. ?動釋放曾經持有的
_mutex鎖 c. 當條件滿?,線程喚醒,pthread_cond_wait要求線性
// 必須重新競爭_mutex鎖,競爭成功,?可返回!!!
// 之前:安全
_productor_wait_num++;
pthread_cond_wait(&_product_cond, &_mutex); // 只要等待,必定會有喚
醒,喚醒的時候,就要繼續從這個位置向下運?!!
_productor_wait_num--;
// 之后:安全
}
// 進??產
// _block_queue.push(std::move(in));
// std::cout << in << std::endl;
_block_queue.push(in);
// 通知消費者來消費
if(_consumer_wait_num > 0)
pthread_cond_signal(&_consum_cond); // pthread_cond_broadcast
pthread_mutex_unlock(&_mutex);
}
void Pop(T *out) // 消費者?的接? --- 5個消費者
{
pthread_mutex_lock(&_mutex);
while(IsEmpty()) // 保證代碼的健壯性
{
// 消費線程去等待,是在臨界區中休眠的!你現在還持有鎖呢!!!
// 1. pthread_cond_wait調?是: a. 讓調?進程等待 b. ?動釋放曾經持有的
_mutex鎖
_consumer_wait_num++;
pthread_cond_wait(&_consum_cond, &_mutex); // 偽喚醒
_consumer_wait_num--;
}// 進?消費
*out = _block_queue.front();
_block_queue.pop();
// 通知?產者來?產
if(_productor_wait_num > 0)
pthread_cond_signal(&_product_cond);
pthread_mutex_unlock(&_mutex);
// pthread_cond_signal(&_product_cond);
}
~BlockQueue()
{
pthread_mutex_destroy(&_mutex);
pthread_cond_destroy(&_product_cond);
pthread_cond_destroy(&_consum_cond);
}
private:
std::queue<T> _block_queue; // 阻塞隊列,是被整體使?的!!!
int _cap; // 總上限
pthread_mutex_t _mutex; // 保護_block_queue的鎖
pthread_cond_t _product_cond; // 專?給?產者提供的條件變量
pthread_cond_t _consum_cond; // 專?給消費者提供的條件變量
int _productor_wait_num;
int _consumer_wait_num;
};📌 注意:這?采?模版,是想告訴我們,隊列中不僅僅可以防?內置類型,?如int, 對象也可
以作為任務來參與?產消費的過程哦.
下?附上?張代碼,?便課堂使?
#pragma once
#include <iostream>
#include <string>
#include <functional>
// 任務類型1
// class Task
// {
// public:
// Task() {}
// Task(int a, int b) : _a(a), _b(b), _result(0)
// {
// }
// void Excute()
// {
// _result = _a + _b;
// }
// std::string ResultToString()
// {
// return std::to_string(_a) + "+" + std::to_string(_b) + "=" +
std::to_string(_result);
// }
// std::string DebugToString()
// {
// return std::to_string(_a) + "+" + std::to_string(_b) + "=?";
// }
// private:
// int _a;
// int _b;
// int _result;
// };
// 任務類型2
using Task = std::function<void()>;

2-3 為什么ptread_cond_wait需要互斥量

條件等待是線程同步的一種手段,如果只有一個線程,條件不滿足,一直等待下去都不會被滿足,所以必須要有一個線程通過某些手段,去改變共享變量,使原先的條件不滿足變成滿足,然后再去友好的通知等待在該條件變量上的線程

條件不會無緣無故的突然變得滿足了,必然牽扯到共享數據的變化,所以一定要用互斥鎖來保護

按照上?的說法,我們設計出如下的代碼:先上鎖,發現條件不滿?,解鎖,然后等待在條件變
量上不就?了,如下代碼:
// 錯誤的設計
pthread_mutex_lock(&mutex);
while (condition_is_false) {
pthread_mutex_unlock(&mutex);
//解鎖之后,等待之前,條件可能已經滿?,信號已經發出,但是該信號可能被錯過
pthread_cond_wait(&cond);
pthread_mutex_lock(&mutex);
}
pthread_mutex_unlock(&mutex);

由于解鎖和等待不是原子性,調用解鎖之后pthread_cond_wait之前,如果有其他的線程獲得互斥量摒棄條件滿?,發送了信號,那么 pthread_cond_wait 將錯過這個信 號,可能會導致線程永遠阻塞在這個 pthread_cond_wait 。所以解鎖和等待必須是?個原?操作。

2-4 條件變量的使用規范

pthread_mutex_lock(&mutex);
while (條件為假)
pthread_cond_wait(cond, mutex);
修改條件
pthread_mutex_unlock(&mutex);

給條件發現信號

pthread_mutex_lock(&mutex);
設置條件為真
pthread_cond_signal(cond);
pthread_mutex_unlock(&mutex);

2-5條件變量的封裝

大家有興趣的可以看一下

test_4_7_線程池/Cond.h · liu xi peng/linux---ubuntu系統 - 碼云 - 開源中國

2-6 POSIX信號量

POSIX信號量和SystemV信號量作用相同,都是用于同步操作,達到無沖突的訪問共享資源,但是OIXIS可以用于線程間同步

初始化

#include <semaphore.h>
int sem_init(sem_t *sem, int pshared, unsigned int value);
參數:
pshared:0表?線程間共享,?零表?進程間共享
value:信號量初始值

銷毀

int sem_destroy(sem_t *sem);

等待

功能:等待信號量,會將信號量的值減1
int sem_wait(sem_t *sem);?
發布
int sem_post(sem_t *sem);

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

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

相關文章

堆排序算法詳解:原理、實現與C語言代碼

堆排序&#xff08;Heap Sort&#xff09;是一種高效的排序算法&#xff0c;利用二叉堆數據結構實現。其核心思想是將待排序序列構造成一個大頂堆&#xff08;或小頂堆&#xff09;&#xff0c;通過反復調整堆結構完成排序。下面從原理到實現進行詳細解析。一、核心概念&#x…

SSM框架——注入類型

引用類型的注入&#xff1a;Setter方法簡單類型的注入&#xff1a;定義簡單實例和方法在配置文件中對bean進行配置&#xff0c;使用porperty屬性 值用value&#xff08;ref是用來獲取bean的&#xff09;構造器方法&#xff1a;構造器方法中需要寫name&#xff0c;這樣程序就會耦…

信息學奧賽一本通 1552:【例 1】點的距離

【題目鏈接】 ybt 1552&#xff1a;【例 1】點的距離 【題目考點】 1. 最近公共祖先&#xff08;LCA&#xff09;&#xff1a;倍增求LCA 知識點講解見&#xff1a;洛谷 P3379 【模板】最近公共祖先&#xff08;LCA&#xff09; 【解題思路】 首先用鄰接表保存輸入的無權圖…

1Panel中的OpenResty使用alias

問題 在服務器上使用了1Panel的OpenResty來管理網站服務&#xff0c;當作是一個Nginx用&#xff0c;想做一個alias來直接管理某個文件夾的文件&#xff0c;于是直接在其中一個網站中使用了alias配置。 location /upload {alias /root/upload;autoindex on;charset utf-8;charse…

小明記賬簿煥新記:從單色到多彩的主題進化之路

【從冷靜藍到多彩世界&#xff0c;這一次我們重新定義記賬美學】 曾經&#xff0c;打開“小明記賬簿”是一片沉穩的藍色海洋&#xff0c;它像一位理性的財務管家&#xff0c;默默守護著你的每一筆收支。但總有人悄悄問&#xff1a;“能不能多一些顏色&#xff1f;”今天&#x…

Apache IoTDB(1):時序數據庫介紹與單機版安裝部署指南

目錄一、Apache IoTDB 是什么&#xff1f;1.1 產品介紹1.2 產品體系1.3 產品架構二、IoTDB 環境配置2.1 Linux系統需準備環境2.2 Windows系統需準備環境2.3 網絡配置2.3.1 關閉防火墻2.3.2 查看端口是否占用2.3.3 避雷經驗三、IoTDB 單機版系統部署安裝指南3.1 產品下載3.2 注意…

Python 圖片爬取入門:從手動下載到自動批量獲取

前言 想批量下載網頁圖片卻嫌手動保存太麻煩&#xff1f;本文用 Python 帶你實現自動爬取&#xff0c;從分析網站到代碼運行&#xff0c;步驟清晰&#xff0c;新手也能快速上手&#xff0c;輕松搞定圖片批量獲取。 1.安裝模塊 在開始爬取圖片前&#xff0c;我們需要準備好工具…

aspect-ratio: 1 / 1樣式在部分手機瀏覽器中失效的問題怎么解決?

最近在uniapp開發時又遇到了安卓手機不兼容問題&#xff0c;ios系統無影響。開發背景&#xff1a;小編想通過網格布局來實現答題卡的布局&#xff0c;實現五列多行的形式。代碼片段&#xff1a;<view class"question-grid"><viewv-for"(question, inde…

RecyclerView與ListView深度對比分析

1. 使用流程對比ListView: 布局XML&#xff1a; 在布局文件中放置 <ListView> 控件&#xff0c;指定 id (如 android:id"id/listView")。數據適配器 (Adapter)&#xff1a; 繼承 BaseAdapter 或 ArrayAdapter / CursorAdapter / SimpleAdapter。 重寫 getCount…

deepseekAI對接大模型的網頁PHP源碼帶管理后臺(可實現上傳分析文件)

前端后端都已進行優化&#xff0c;新增可上傳文件功能&#xff08;拖拽進去也可以&#xff09;&#xff0c;后端進行風格主題設置&#xff0c;優化數據結構&#xff01;依舊測試網站&#xff1a;iEPMS我的工具箱&#xff0c;你的智慧助手&#xff01;還是那句話兄弟們輕點搞我的…

NJU 凸優化導論(9) 對偶(II)KKT條件+變形重構

https://www.lamda.nju.edu.cn/chengq/optfall24/slides/Lecture_9.pdf 目錄 關于對偶的一些解釋 1. Max-min characterization 最大最小準則 2. Saddle-point Interpretation 鞍點解釋 3. Game interpretation 博弈論里的對偶 Optimality Conditions 最優條件 1. Certi…

Vue Swiper組件

Vue 漸進式JavaScript 框架 基于Vue2的學習筆記 - Vue Swiper組件實現筆記 目錄 Swiper組件 下載swiper 創建swiper組件 保存時修復 編寫swiper內容 引入swiper 使用swiper Swiper子組件 創建Swiper列表組件 使用子組件 增加生命周期 增加圖片顯示 加載數據 渲染…

Linux:lvs集群技術

一.集群和分布式1.1 集群集群是為了解決某個特定問題將多臺計算機組合起來形成的單個系統。即當單獨一臺主機無法承載現有的用戶請求量&#xff1b;或者一臺主機因為單一故障導致業務中斷的時候&#xff0c;就可以增加服務主機數&#xff0c;這些主機在一起提供服務&#xff0c…

【管理】持續交付2.0:業務引領的DevOps-精要增訂本,讀書筆記(理論模型,技術架構,業務價值)

【管理】持續交付2.0&#xff1a;業務引領的DevOps-精要增訂本&#xff0c;讀書筆記&#xff08;理論模型&#xff0c;技術架構&#xff0c;業務價值&#xff09; 文章目錄1、持續交付的理論模型&#xff08;第1-3章&#xff09;1.1 結構圖1.2 持續交付的演進1.3 雙環模型理論體…

Wilcox檢驗的星星怎么規定的?

在 R 里&#xff0c;常見的把 p 值映射為“星號”標記&#xff08;顯著性水平&#xff09;的規則通常是&#xff1a;p 值范圍標記p ≤ 0.0001“****”0.0001 < p ≤ 0.001“***”0.001 < p ≤ 0.01“**”0.01 < p ≤ 0.05“*”0.05 < p ≤ 0.1“.”p > 0.1…

https與DNS的運行流程

HTTPS流程&#xff1a;HTTPS核心:加了TLS層&#xff0c;加密傳輸身份認證TLS:信息加密、校驗機制、身份證書TLS&#xff08;Transport Layer Security&#xff09;握手是建立安全通信通道的關鍵過程&#xff0c;發生在客戶端&#xff08;如瀏覽器&#xff09;和服務器之間。其主…

板子 5.29--7.19

板子 5.29–7.19 目錄 1. 樹狀數組 2. KMP 3. 矩陣快速冪 4. 數位DP 5. 狀壓枚舉子集 6. 快速冪&#xff08;新版 7. priority_queue 8. dijkstra 9. 單調棧 10. debug內容 1. 樹狀數組 // 樹狀數組 快速求前綴和 / 前綴最大值 // 維護位置數量(離散化)...// (區間加 區間求和…

min-max容斥學習筆記

最近報了航電的春季賽&#xff0c;在一道題目里面遇到了做法&#xff0c;感覺挺有意思。 考慮一個&#xff08;多重&#xff09;集合S{ai}S\{a_i\}S{ai?}&#xff0c;有如下的等式成立 min?ai∈S(ai)∑T?S,T≠?(?1)∣T∣?1max?ai∈T(ai)\min_{a_i\in S}(a_i)\sum_{T\sub…

使用帆軟制作項目

https://zhuanlan.zhihu.com/p/23429318335 項目背景 為加快大數據體系建設&#xff0c;穩步推進數字化轉型戰略&#xff0c;規范數據架構體系和數據治理體系&#xff0c;運用大數據推進全行數字化轉型建設&#xff0c;為業務發展提供創新動力&#xff0c;目標是利用金融科技和…

論C/C++的條件編譯#if、#ifdef、#ifndef、#undef

我們以實例來演示&#xff1a; ------------------------------------------實驗①------------------------------------------ 子函數&#xff1a;主函數&#xff1a;當定義了COMMENT_FLAG該宏&#xff0c;且其為0&#xff0c;則運行結果如下&#xff1a;只執行了sub_func_1函…